switch to bootstrap 4
This commit is contained in:
parent
93f7335b6e
commit
461a339ada
|
@ -0,0 +1,190 @@
|
||||||
|
// Lux 4.5.3
|
||||||
|
// Bootswatch
|
||||||
|
|
||||||
|
|
||||||
|
// Variables ===================================================================
|
||||||
|
|
||||||
|
$web-font-path: "https://fonts.googleapis.com/css2?family=Nunito+Sans:wght@400;600&display=swap" !default;
|
||||||
|
@import url($web-font-path);
|
||||||
|
|
||||||
|
// Navbar ======================================================================
|
||||||
|
|
||||||
|
.navbar {
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-weight: 600;
|
||||||
|
|
||||||
|
&-nav {
|
||||||
|
.nav-link {
|
||||||
|
padding-top: .715rem;
|
||||||
|
padding-bottom: .715rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-brand {
|
||||||
|
margin-right: 2rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-primary {
|
||||||
|
background-color: theme-color("primary") !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-light {
|
||||||
|
border: 1px solid rgba(0, 0, 0, .1);
|
||||||
|
|
||||||
|
&.navbar-fixed-top {
|
||||||
|
border-width: 0 0 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.navbar-bottom-top {
|
||||||
|
border-width: 1px 0 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-item {
|
||||||
|
margin-right: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Buttons =====================================================================
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
text-transform: uppercase;
|
||||||
|
|
||||||
|
&-sm {
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-warning {
|
||||||
|
&,
|
||||||
|
&:hover,
|
||||||
|
&:not([disabled]):not(.disabled):active,
|
||||||
|
&:focus {
|
||||||
|
color: $white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-outline-secondary {
|
||||||
|
border-color: $gray-600;
|
||||||
|
color: $gray-600;
|
||||||
|
|
||||||
|
&:not([disabled]):not(.disabled):hover,
|
||||||
|
&:not([disabled]):not(.disabled):focus,
|
||||||
|
&:not([disabled]):not(.disabled):active {
|
||||||
|
background-color: $gray-400;
|
||||||
|
border-color: $gray-400;
|
||||||
|
color: $white;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not([disabled]):not(.disabled):focus {
|
||||||
|
box-shadow: 0 0 0 .2rem rgba($gray-400, .5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[class*="btn-outline-"] {
|
||||||
|
border-width: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.border-secondary {
|
||||||
|
border: 1px solid $gray-400 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Typography ==================================================================
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-weight: 200;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-secondary {
|
||||||
|
color: $body-color !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tables ======================================================================
|
||||||
|
|
||||||
|
th {
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table {
|
||||||
|
th,
|
||||||
|
td {
|
||||||
|
padding: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-sm {
|
||||||
|
th,
|
||||||
|
td {
|
||||||
|
padding: .75rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Forms =======================================================================
|
||||||
|
|
||||||
|
.custom-switch {
|
||||||
|
.custom-control-label {
|
||||||
|
&::after {
|
||||||
|
top: add(.15625rem, 2px);
|
||||||
|
left: add(-2.25rem, 2px);
|
||||||
|
width: subtract(1rem, 4px);
|
||||||
|
height: subtract(1rem, 4px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Navs ========================================================================
|
||||||
|
|
||||||
|
.dropdown-menu {
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
text-transform: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Indicators ==================================================================
|
||||||
|
|
||||||
|
.badge {
|
||||||
|
padding-top: .28rem;
|
||||||
|
|
||||||
|
&-pill {
|
||||||
|
border-radius: 10rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Containers ==================================================================
|
||||||
|
|
||||||
|
.list-group-item {
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6,
|
||||||
|
.h1,
|
||||||
|
.h2,
|
||||||
|
.h3,
|
||||||
|
.h4,
|
||||||
|
.h5,
|
||||||
|
.h6 {
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
&-title,
|
||||||
|
&-header {
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,106 @@
|
||||||
|
// Lux 4.5.3
|
||||||
|
// Bootswatch
|
||||||
|
|
||||||
|
//
|
||||||
|
// Color system
|
||||||
|
//
|
||||||
|
|
||||||
|
$white: #fff !default;
|
||||||
|
$gray-100: #f8f9fa !default;
|
||||||
|
$gray-200: #f7f7f9 !default;
|
||||||
|
$gray-300: #eceeef !default;
|
||||||
|
$gray-400: #ced4da !default;
|
||||||
|
$gray-500: #adb5bd !default;
|
||||||
|
$gray-600: #919aa1 !default;
|
||||||
|
$gray-700: #55595c !default;
|
||||||
|
$gray-800: #343a40 !default;
|
||||||
|
$gray-900: #1a1a1a !default;
|
||||||
|
$black: #000 !default;
|
||||||
|
|
||||||
|
$blue: #007bff !default;
|
||||||
|
$indigo: #6610f2 !default;
|
||||||
|
$purple: #6f42c1 !default;
|
||||||
|
$pink: #e83e8c !default;
|
||||||
|
$red: #d9534f !default;
|
||||||
|
$orange: #fd7e14 !default;
|
||||||
|
$yellow: #f0ad4e !default;
|
||||||
|
$green: #4bbf73 !default;
|
||||||
|
$teal: #20c997 !default;
|
||||||
|
$cyan: #1f9bcf !default;
|
||||||
|
|
||||||
|
$primary: $gray-900 !default;
|
||||||
|
$secondary: $white !default;
|
||||||
|
$success: $green !default;
|
||||||
|
$info: $cyan !default;
|
||||||
|
$warning: $yellow !default;
|
||||||
|
$danger: $red !default;
|
||||||
|
$light: $white !default;
|
||||||
|
$dark: $gray-800 !default;
|
||||||
|
|
||||||
|
$yiq-contrasted-threshold: 185 !default;
|
||||||
|
|
||||||
|
// Options
|
||||||
|
|
||||||
|
$enable-rounded: false !default;
|
||||||
|
|
||||||
|
// Body
|
||||||
|
|
||||||
|
$body-color: $gray-700 !default;
|
||||||
|
|
||||||
|
// Fonts
|
||||||
|
|
||||||
|
// stylelint-disable-next-line value-keyword-case
|
||||||
|
$font-family-sans-serif: "Nunito Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol" !default;
|
||||||
|
$font-size-base: .875rem !default;
|
||||||
|
$h1-font-size: 2rem !default;
|
||||||
|
$h2-font-size: 1.75rem !default;
|
||||||
|
$h3-font-size: 1.5rem !default;
|
||||||
|
$h4-font-size: 1.25rem !default;
|
||||||
|
$h5-font-size: 1rem !default;
|
||||||
|
$h6-font-size: .75rem !default;
|
||||||
|
$headings-font-weight: 600 !default;
|
||||||
|
$headings-color: $gray-900 !default;
|
||||||
|
|
||||||
|
// Tables
|
||||||
|
|
||||||
|
$table-border-color: rgba(0, 0, 0, .05) !default;
|
||||||
|
|
||||||
|
// Buttons + Forms
|
||||||
|
|
||||||
|
$input-btn-border-width: 0 !default;
|
||||||
|
|
||||||
|
// Buttons
|
||||||
|
|
||||||
|
$btn-line-height: 1.5rem !default;
|
||||||
|
$input-btn-padding-y: .75rem !default;
|
||||||
|
$input-btn-padding-x: 1.5rem !default;
|
||||||
|
$input-btn-padding-y-sm: .5rem !default;
|
||||||
|
$input-btn-padding-x-sm: 1rem !default;
|
||||||
|
$input-btn-padding-y-lg: 2rem !default;
|
||||||
|
$input-btn-padding-x-lg: 2rem !default;
|
||||||
|
$btn-font-weight: 600 !default;
|
||||||
|
|
||||||
|
// Forms
|
||||||
|
|
||||||
|
$input-line-height: 1.5 !default;
|
||||||
|
$input-bg: $gray-200 !default;
|
||||||
|
$input-disabled-bg: $gray-300 !default;
|
||||||
|
$input-group-addon-bg: $gray-300 !default;
|
||||||
|
|
||||||
|
// Navbar
|
||||||
|
|
||||||
|
$navbar-padding-y: 1.5rem !default;
|
||||||
|
$navbar-dark-hover-color: $white !default;
|
||||||
|
$navbar-light-color: rgba($black, .3) !default;
|
||||||
|
$navbar-light-hover-color: $gray-900 !default;
|
||||||
|
$navbar-light-active-color: $gray-900 !default;
|
||||||
|
|
||||||
|
// Pagination
|
||||||
|
|
||||||
|
$pagination-border-color: transparent !default;
|
||||||
|
$pagination-hover-border-color: $pagination-border-color !default;
|
||||||
|
$pagination-disabled-border-color: $pagination-border-color !default;
|
||||||
|
|
||||||
|
// Breadcrumbs
|
||||||
|
|
||||||
|
$breadcrumb-bg: transparent !default;
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
@ -1,54 +1,5 @@
|
||||||
/* Sticky footer styles
|
/* Start collapsable table
|
||||||
-------------------------------------------------- */
|
-------------------------------------------------- */
|
||||||
html {
|
|
||||||
position: relative;
|
|
||||||
min-height: 100%;
|
|
||||||
}
|
|
||||||
body {
|
|
||||||
/* Margin bottom by footer height */
|
|
||||||
margin-bottom: 60px;
|
|
||||||
}
|
|
||||||
.footer {
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
width: 100%;
|
|
||||||
/* Set the fixed height of the footer here */
|
|
||||||
height: 60px;
|
|
||||||
background-color: #f5f5f5;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Custom page CSS
|
|
||||||
-------------------------------------------------- */
|
|
||||||
/* Not required for template or sticky footer method. */
|
|
||||||
|
|
||||||
body > .container {
|
|
||||||
padding: 60px 15px 0;
|
|
||||||
}
|
|
||||||
.container .text-muted {
|
|
||||||
margin: 20px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer > .container {
|
|
||||||
padding-right: 15px;
|
|
||||||
padding-left: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
code {
|
|
||||||
font-size: 80%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-spacer {
|
|
||||||
min-width: 100px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navbar-brand {
|
|
||||||
padding: 3px 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.scroll-to-top {
|
|
||||||
float: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hiddenRow, .hiddenCell {
|
.hiddenRow, .hiddenCell {
|
||||||
padding: 0px!important;
|
padding: 0px!important;
|
||||||
|
@ -60,117 +11,40 @@ code {
|
||||||
}
|
}
|
||||||
|
|
||||||
.collapsedRow {
|
.collapsedRow {
|
||||||
padding: 10px 30px;
|
padding: 10px 0px;
|
||||||
border-top: 1px solid lightgray;
|
border-top: 1px solid lightgray;
|
||||||
|
margin-left: 0px;
|
||||||
|
margin-right: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.leftBorder {
|
.collapse-indicator {
|
||||||
border-left: 2px solid black;
|
|
||||||
}
|
|
||||||
|
|
||||||
#userTable .collapse-indicator {
|
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#userTable .collapse-indicator:after {
|
.collapse-indicator:after {
|
||||||
font-weight: 900;
|
font-weight: 900;
|
||||||
font-family: "Font Awesome 5 Free";
|
font-family: "Font Awesome 5 Free";
|
||||||
content: "\f056";
|
content: "\f056";
|
||||||
}
|
}
|
||||||
#userTable .collapse-indicator.collapsed:after {
|
.collapse-indicator.collapsed:after {
|
||||||
font-weight: 900;
|
font-weight: 900;
|
||||||
font-family: "Font Awesome 5 Free";
|
font-family: "Font Awesome 5 Free";
|
||||||
content: "\f055";
|
content: "\f055";
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-group .btn {
|
/* --------------------------------------------------
|
||||||
background: #999;
|
End collapsable table*/
|
||||||
color: #000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-group .btn:hover {
|
@media (min-width: 1440px) {
|
||||||
background: #444;
|
.container, .container-lg, .container-md, .container-sm, .container-xl {
|
||||||
color: #ddd;
|
max-width: 1400px;
|
||||||
}
|
|
||||||
|
|
||||||
.btn-group .btn.active {
|
|
||||||
background: #000;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.list-image-small {
|
|
||||||
height: 7vh;
|
|
||||||
width: auto;
|
|
||||||
background-size: cover;
|
|
||||||
}
|
|
||||||
|
|
||||||
.list-image-large {
|
|
||||||
height: 20vh;
|
|
||||||
width: auto;
|
|
||||||
background-size: cover;
|
|
||||||
}
|
|
||||||
|
|
||||||
.list-image-edit {
|
|
||||||
height: 23vh;
|
|
||||||
width: auto;
|
|
||||||
background-size: cover;
|
|
||||||
}
|
|
||||||
|
|
||||||
.list-image-cell {
|
|
||||||
width: 140px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#userTable tr td {
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
#inputThumbnailPhoto {
|
|
||||||
padding-top: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-edit-jumbotron {
|
|
||||||
border: 2px solid black;
|
|
||||||
padding-top:40px;
|
|
||||||
padding-bottom:40px;
|
|
||||||
margin-bottom: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#searchclear {
|
|
||||||
position: absolute;
|
|
||||||
right: 5px;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
height: 18px;
|
|
||||||
margin: auto;
|
|
||||||
font-size: 14px;
|
|
||||||
cursor: pointer;
|
|
||||||
color: #979797;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type="search"]::-webkit-search-cancel-button {
|
|
||||||
-webkit-appearance: searchfield-cancel-button;
|
|
||||||
}
|
|
||||||
|
|
||||||
.alert {
|
|
||||||
margin-bottom: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 1200px) {
|
|
||||||
.container {
|
|
||||||
width: 1150px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-edit-container {
|
|
||||||
width: 1100px;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 1600px) {
|
.device-status-table {
|
||||||
.container {
|
font-size: small;
|
||||||
width: 1600px;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.user-edit-container {
|
.navbar {
|
||||||
width: 1100px;
|
padding: 0.5rem 1rem;
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -1,40 +0,0 @@
|
||||||
body {
|
|
||||||
padding-top: 40px;
|
|
||||||
padding-bottom: 40px;
|
|
||||||
background-color: #eee;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-signin {
|
|
||||||
max-width: 330px;
|
|
||||||
padding: 15px;
|
|
||||||
margin: 0 auto;
|
|
||||||
}
|
|
||||||
.form-signin .form-signin-heading,
|
|
||||||
.form-signin .checkbox {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
.form-signin .checkbox {
|
|
||||||
font-weight: normal;
|
|
||||||
}
|
|
||||||
.form-signin .form-control {
|
|
||||||
position: relative;
|
|
||||||
height: auto;
|
|
||||||
-webkit-box-sizing: border-box;
|
|
||||||
-moz-box-sizing: border-box;
|
|
||||||
box-sizing: border-box;
|
|
||||||
padding: 10px;
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
.form-signin .form-control:focus {
|
|
||||||
z-index: 2;
|
|
||||||
}
|
|
||||||
.form-signin input[type="email"] {
|
|
||||||
margin-bottom: -1px;
|
|
||||||
border-bottom-right-radius: 0;
|
|
||||||
border-bottom-left-radius: 0;
|
|
||||||
}
|
|
||||||
.form-signin input[type="password"] {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
border-top-left-radius: 0;
|
|
||||||
border-top-right-radius: 0;
|
|
||||||
}
|
|
|
@ -1,879 +0,0 @@
|
||||||
// Generated by PaintStrap
|
|
||||||
// http://paintstrap.com/
|
|
||||||
|
|
||||||
//
|
|
||||||
// Variables
|
|
||||||
// --------------------------------------------------
|
|
||||||
|
|
||||||
@ps-text: #000000;
|
|
||||||
@ps-nav-bg: #000000;
|
|
||||||
@ps-link-text: #000000;
|
|
||||||
@ps-nav-text: #FFFFFF;
|
|
||||||
@ps-well-bg: #FFFFFF;
|
|
||||||
@ps-jumbotron-bg: #FFFFFF;
|
|
||||||
@ps-bg: #FFFFFF;
|
|
||||||
|
|
||||||
//== Colors
|
|
||||||
//
|
|
||||||
//## Gray and brand colors for use across Bootstrap.
|
|
||||||
|
|
||||||
@gray-base: #000;
|
|
||||||
@gray-darker: lighten(@gray-base, 13.5%); // #222
|
|
||||||
@gray-dark: lighten(@gray-base, 20%); // #333
|
|
||||||
@gray: lighten(@gray-base, 33.5%); // #555
|
|
||||||
@gray-light: lighten(@gray-base, 46.7%); // #777
|
|
||||||
@gray-lighter: lighten(@gray-base, 93.5%); // #eee
|
|
||||||
|
|
||||||
@brand-primary: @ps-link-text;
|
|
||||||
@brand-success: #5cb85c;
|
|
||||||
@brand-info: #5bc0de;
|
|
||||||
@brand-warning: #f0ad4e;
|
|
||||||
@brand-danger: #d9534f;
|
|
||||||
|
|
||||||
|
|
||||||
//== Scaffolding
|
|
||||||
//
|
|
||||||
//## Settings for some of the most global styles.
|
|
||||||
|
|
||||||
//** Background color for `<body>`.
|
|
||||||
@body-bg: @ps-bg;
|
|
||||||
//** Global text color on `<body>`.
|
|
||||||
@text-color: @ps-text;
|
|
||||||
|
|
||||||
//** Global textual link color.
|
|
||||||
@link-color: @brand-primary;
|
|
||||||
//** Link hover color set via `darken()` function.
|
|
||||||
@link-hover-color: darken(@link-color, 15%);
|
|
||||||
//** Link hover decoration.
|
|
||||||
@link-hover-decoration: underline;
|
|
||||||
|
|
||||||
|
|
||||||
//== Typography
|
|
||||||
//
|
|
||||||
//## Font, line-height, and color for body text, headings, and more.
|
|
||||||
|
|
||||||
@font-family-sans-serif: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
|
||||||
@font-family-serif: Georgia, "Times New Roman", Times, serif;
|
|
||||||
//** Default monospace fonts for `<code>`, `<kbd>`, and `<pre>`.
|
|
||||||
@font-family-monospace: Menlo, Monaco, Consolas, "Courier New", monospace;
|
|
||||||
@font-family-base: @font-family-sans-serif;
|
|
||||||
|
|
||||||
@font-size-base: 14px;
|
|
||||||
@font-size-large: ceil((@font-size-base * 1.25)); // ~18px
|
|
||||||
@font-size-small: ceil((@font-size-base * 0.85)); // ~12px
|
|
||||||
|
|
||||||
@font-size-h1: floor((@font-size-base * 2.6)); // ~36px
|
|
||||||
@font-size-h2: floor((@font-size-base * 2.15)); // ~30px
|
|
||||||
@font-size-h3: ceil((@font-size-base * 1.7)); // ~24px
|
|
||||||
@font-size-h4: ceil((@font-size-base * 1.25)); // ~18px
|
|
||||||
@font-size-h5: @font-size-base;
|
|
||||||
@font-size-h6: ceil((@font-size-base * 0.85)); // ~12px
|
|
||||||
|
|
||||||
//** Unit-less `line-height` for use in components like buttons.
|
|
||||||
@line-height-base: 1.428571429; // 20/14
|
|
||||||
//** Computed "line-height" (`font-size` * `line-height`) for use with `margin`, `padding`, etc.
|
|
||||||
@line-height-computed: floor((@font-size-base * @line-height-base)); // ~20px
|
|
||||||
|
|
||||||
//** By default, this inherits from the `<body>`.
|
|
||||||
@headings-font-family: inherit;
|
|
||||||
@headings-font-weight: 500;
|
|
||||||
@headings-line-height: 1.1;
|
|
||||||
@headings-color: inherit;
|
|
||||||
|
|
||||||
|
|
||||||
//== Iconography
|
|
||||||
//
|
|
||||||
//## Specify custom location and filename of the included Glyphicons icon font. Useful for those including Bootstrap via Bower.
|
|
||||||
|
|
||||||
//** Load fonts from this directory.
|
|
||||||
@icon-font-path: "../fonts/";
|
|
||||||
//** File name for all font files.
|
|
||||||
@icon-font-name: "glyphicons-halflings-regular";
|
|
||||||
//** Element ID within SVG icon file.
|
|
||||||
@icon-font-svg-id: "glyphicons_halflingsregular";
|
|
||||||
|
|
||||||
|
|
||||||
//== Components
|
|
||||||
//
|
|
||||||
//## Define common padding and border radius sizes and more. Values based on 14px text and 1.428 line-height (~20px to start).
|
|
||||||
|
|
||||||
@padding-base-vertical: 6px;
|
|
||||||
@padding-base-horizontal: 12px;
|
|
||||||
|
|
||||||
@padding-large-vertical: 10px;
|
|
||||||
@padding-large-horizontal: 16px;
|
|
||||||
|
|
||||||
@padding-small-vertical: 5px;
|
|
||||||
@padding-small-horizontal: 10px;
|
|
||||||
|
|
||||||
@padding-xs-vertical: 1px;
|
|
||||||
@padding-xs-horizontal: 5px;
|
|
||||||
|
|
||||||
@line-height-large: 1.3333333; // extra decimals for Win 8.1 Chrome
|
|
||||||
@line-height-small: 1.5;
|
|
||||||
|
|
||||||
@border-radius-base: 4px;
|
|
||||||
@border-radius-large: 6px;
|
|
||||||
@border-radius-small: 3px;
|
|
||||||
|
|
||||||
//** Global color for active items (e.g., navs or dropdowns).
|
|
||||||
@component-active-color: #fff;
|
|
||||||
//** Global background color for active items (e.g., navs or dropdowns).
|
|
||||||
@component-active-bg: @brand-primary;
|
|
||||||
|
|
||||||
//** Width of the `border` for generating carets that indicate dropdowns.
|
|
||||||
@caret-width-base: 4px;
|
|
||||||
//** Carets increase slightly in size for larger components.
|
|
||||||
@caret-width-large: 5px;
|
|
||||||
|
|
||||||
|
|
||||||
//== Tables
|
|
||||||
//
|
|
||||||
//## Customizes the `.table` component with basic values, each used across all table variations.
|
|
||||||
|
|
||||||
//** Padding for `<th>`s and `<td>`s.
|
|
||||||
@table-cell-padding: 8px;
|
|
||||||
//** Padding for cells in `.table-condensed`.
|
|
||||||
@table-condensed-cell-padding: 5px;
|
|
||||||
|
|
||||||
//** Default background color used for all tables.
|
|
||||||
@table-bg: transparent;
|
|
||||||
//** Background color used for `.table-striped`.
|
|
||||||
@table-bg-accent: #f9f9f9;
|
|
||||||
//** Background color used for `.table-hover`.
|
|
||||||
@table-bg-hover: #f5f5f5;
|
|
||||||
@table-bg-active: @table-bg-hover;
|
|
||||||
|
|
||||||
//** Border color for table and cell borders.
|
|
||||||
@table-border-color: #ddd;
|
|
||||||
|
|
||||||
|
|
||||||
//== Buttons
|
|
||||||
//
|
|
||||||
//## For each of Bootstrap's buttons, define text, background and border color.
|
|
||||||
|
|
||||||
@btn-font-weight: normal;
|
|
||||||
|
|
||||||
@btn-default-color: #333;
|
|
||||||
@btn-default-bg: #fff;
|
|
||||||
@btn-default-border: #ccc;
|
|
||||||
|
|
||||||
@btn-primary-color: contrast(@brand-primary, black, white);
|
|
||||||
@btn-primary-bg: @brand-primary;
|
|
||||||
@btn-primary-border: darken(@btn-primary-bg, 5%);
|
|
||||||
|
|
||||||
@btn-success-color: #fff;
|
|
||||||
@btn-success-bg: @brand-success;
|
|
||||||
@btn-success-border: darken(@btn-success-bg, 5%);
|
|
||||||
|
|
||||||
@btn-info-color: #fff;
|
|
||||||
@btn-info-bg: @brand-info;
|
|
||||||
@btn-info-border: darken(@btn-info-bg, 5%);
|
|
||||||
|
|
||||||
@btn-warning-color: #fff;
|
|
||||||
@btn-warning-bg: @brand-warning;
|
|
||||||
@btn-warning-border: darken(@btn-warning-bg, 5%);
|
|
||||||
|
|
||||||
@btn-danger-color: #fff;
|
|
||||||
@btn-danger-bg: @brand-danger;
|
|
||||||
@btn-danger-border: darken(@btn-danger-bg, 5%);
|
|
||||||
|
|
||||||
@btn-link-disabled-color: @gray-light;
|
|
||||||
|
|
||||||
// Allows for customizing button radius independently from global border radius
|
|
||||||
@btn-border-radius-base: @border-radius-base;
|
|
||||||
@btn-border-radius-large: @border-radius-large;
|
|
||||||
@btn-border-radius-small: @border-radius-small;
|
|
||||||
|
|
||||||
|
|
||||||
//== Forms
|
|
||||||
//
|
|
||||||
//##
|
|
||||||
|
|
||||||
//** `<input>` background color
|
|
||||||
@input-bg: #fff;
|
|
||||||
//** `<input disabled>` background color
|
|
||||||
@input-bg-disabled: @gray-lighter;
|
|
||||||
|
|
||||||
//** Text color for `<input>`s
|
|
||||||
@input-color: @gray;
|
|
||||||
//** `<input>` border color
|
|
||||||
@input-border: #ccc;
|
|
||||||
|
|
||||||
// TODO: Rename `@input-border-radius` to `@input-border-radius-base` in v4
|
|
||||||
//** Default `.form-control` border radius
|
|
||||||
// This has no effect on `<select>`s in some browsers, due to the limited stylability of `<select>`s in CSS.
|
|
||||||
@input-border-radius: @border-radius-base;
|
|
||||||
//** Large `.form-control` border radius
|
|
||||||
@input-border-radius-large: @border-radius-large;
|
|
||||||
//** Small `.form-control` border radius
|
|
||||||
@input-border-radius-small: @border-radius-small;
|
|
||||||
|
|
||||||
//** Border color for inputs on focus
|
|
||||||
@input-border-focus: #66afe9;
|
|
||||||
|
|
||||||
//** Placeholder text color
|
|
||||||
@input-color-placeholder: #999;
|
|
||||||
|
|
||||||
//** Default `.form-control` height
|
|
||||||
@input-height-base: (@line-height-computed + (@padding-base-vertical * 2) + 2);
|
|
||||||
//** Large `.form-control` height
|
|
||||||
@input-height-large: (ceil(@font-size-large * @line-height-large) + (@padding-large-vertical * 2) + 2);
|
|
||||||
//** Small `.form-control` height
|
|
||||||
@input-height-small: (floor(@font-size-small * @line-height-small) + (@padding-small-vertical * 2) + 2);
|
|
||||||
|
|
||||||
//** `.form-group` margin
|
|
||||||
@form-group-margin-bottom: 15px;
|
|
||||||
|
|
||||||
@legend-color: @gray-dark;
|
|
||||||
@legend-border-color: #e5e5e5;
|
|
||||||
|
|
||||||
//** Background color for textual input addons
|
|
||||||
@input-group-addon-bg: @gray-lighter;
|
|
||||||
//** Border color for textual input addons
|
|
||||||
@input-group-addon-border-color: @input-border;
|
|
||||||
|
|
||||||
//** Disabled cursor for form controls and buttons.
|
|
||||||
@cursor-disabled: not-allowed;
|
|
||||||
|
|
||||||
|
|
||||||
//== Dropdowns
|
|
||||||
//
|
|
||||||
//## Dropdown menu container and contents.
|
|
||||||
|
|
||||||
//** Background for the dropdown menu.
|
|
||||||
@dropdown-bg: @navbar-default-bg;
|
|
||||||
//** Dropdown menu `border-color`.
|
|
||||||
@dropdown-border: rgba(0,0,0,.15);
|
|
||||||
//** Dropdown menu `border-color` **for IE8**.
|
|
||||||
@dropdown-fallback-border: #ccc;
|
|
||||||
//** Divider color for between dropdown items.
|
|
||||||
@dropdown-divider-bg: #e5e5e5;
|
|
||||||
|
|
||||||
//** Dropdown link text color.
|
|
||||||
@dropdown-link-color: @ps-nav-text;
|
|
||||||
//** Hover color for dropdown links.
|
|
||||||
@dropdown-link-hover-color: #fff;
|
|
||||||
//** Hover background for dropdown links.
|
|
||||||
@dropdown-link-hover-bg: @dropdown-link-active-bg;
|
|
||||||
|
|
||||||
//** Active dropdown menu item text color.
|
|
||||||
@dropdown-link-active-color: @component-active-color;
|
|
||||||
//** Active dropdown menu item background color.
|
|
||||||
@dropdown-link-active-bg: @component-active-bg;
|
|
||||||
|
|
||||||
//** Disabled dropdown menu item background color.
|
|
||||||
@dropdown-link-disabled-color: @gray-light;
|
|
||||||
|
|
||||||
//** Text color for headers within dropdown menus.
|
|
||||||
@dropdown-header-color: @gray-light;
|
|
||||||
|
|
||||||
//** Deprecated `@dropdown-caret-color` as of v3.1.0
|
|
||||||
@dropdown-caret-color: #000;
|
|
||||||
|
|
||||||
|
|
||||||
//-- Z-index master list
|
|
||||||
//
|
|
||||||
// Warning: Avoid customizing these values. They're used for a bird's eye view
|
|
||||||
// of components dependent on the z-axis and are designed to all work together.
|
|
||||||
//
|
|
||||||
// Note: These variables are not generated into the Customizer.
|
|
||||||
|
|
||||||
@zindex-navbar: 1000;
|
|
||||||
@zindex-dropdown: 1000;
|
|
||||||
@zindex-popover: 1060;
|
|
||||||
@zindex-tooltip: 1070;
|
|
||||||
@zindex-navbar-fixed: 1030;
|
|
||||||
@zindex-modal-background: 1040;
|
|
||||||
@zindex-modal: 1050;
|
|
||||||
|
|
||||||
|
|
||||||
//== Media queries breakpoints
|
|
||||||
//
|
|
||||||
//## Define the breakpoints at which your layout will change, adapting to different screen sizes.
|
|
||||||
|
|
||||||
// Extra small screen / phone
|
|
||||||
//** Deprecated `@screen-xs` as of v3.0.1
|
|
||||||
@screen-xs: 480px;
|
|
||||||
//** Deprecated `@screen-xs-min` as of v3.2.0
|
|
||||||
@screen-xs-min: @screen-xs;
|
|
||||||
//** Deprecated `@screen-phone` as of v3.0.1
|
|
||||||
@screen-phone: @screen-xs-min;
|
|
||||||
|
|
||||||
// Small screen / tablet
|
|
||||||
//** Deprecated `@screen-sm` as of v3.0.1
|
|
||||||
@screen-sm: 768px;
|
|
||||||
@screen-sm-min: @screen-sm;
|
|
||||||
//** Deprecated `@screen-tablet` as of v3.0.1
|
|
||||||
@screen-tablet: @screen-sm-min;
|
|
||||||
|
|
||||||
// Medium screen / desktop
|
|
||||||
//** Deprecated `@screen-md` as of v3.0.1
|
|
||||||
@screen-md: 992px;
|
|
||||||
@screen-md-min: @screen-md;
|
|
||||||
//** Deprecated `@screen-desktop` as of v3.0.1
|
|
||||||
@screen-desktop: @screen-md-min;
|
|
||||||
|
|
||||||
// Large screen / wide desktop
|
|
||||||
//** Deprecated `@screen-lg` as of v3.0.1
|
|
||||||
@screen-lg: 1200px;
|
|
||||||
@screen-lg-min: @screen-lg;
|
|
||||||
//** Deprecated `@screen-lg-desktop` as of v3.0.1
|
|
||||||
@screen-lg-desktop: @screen-lg-min;
|
|
||||||
|
|
||||||
// So media queries don't overlap when required, provide a maximum
|
|
||||||
@screen-xs-max: (@screen-sm-min - 1);
|
|
||||||
@screen-sm-max: (@screen-md-min - 1);
|
|
||||||
@screen-md-max: (@screen-lg-min - 1);
|
|
||||||
|
|
||||||
|
|
||||||
//== Grid system
|
|
||||||
//
|
|
||||||
//## Define your custom responsive grid.
|
|
||||||
|
|
||||||
//** Number of columns in the grid.
|
|
||||||
@grid-columns: 12;
|
|
||||||
//** Padding between columns. Gets divided in half for the left and right.
|
|
||||||
@grid-gutter-width: 30px;
|
|
||||||
// Navbar collapse
|
|
||||||
//** Point at which the navbar becomes uncollapsed.
|
|
||||||
@grid-float-breakpoint: @screen-sm-min;
|
|
||||||
//** Point at which the navbar begins collapsing.
|
|
||||||
@grid-float-breakpoint-max: (@grid-float-breakpoint - 1);
|
|
||||||
|
|
||||||
|
|
||||||
//== Container sizes
|
|
||||||
//
|
|
||||||
//## Define the maximum width of `.container` for different screen sizes.
|
|
||||||
|
|
||||||
// Small screen / tablet
|
|
||||||
@container-tablet: (720px + @grid-gutter-width);
|
|
||||||
//** For `@screen-sm-min` and up.
|
|
||||||
@container-sm: @container-tablet;
|
|
||||||
|
|
||||||
// Medium screen / desktop
|
|
||||||
@container-desktop: (940px + @grid-gutter-width);
|
|
||||||
//** For `@screen-md-min` and up.
|
|
||||||
@container-md: @container-desktop;
|
|
||||||
|
|
||||||
// Large screen / wide desktop
|
|
||||||
@container-large-desktop: (1140px + @grid-gutter-width);
|
|
||||||
//** For `@screen-lg-min` and up.
|
|
||||||
@container-lg: @container-large-desktop;
|
|
||||||
|
|
||||||
|
|
||||||
//== Navbar
|
|
||||||
//
|
|
||||||
//##
|
|
||||||
|
|
||||||
// Basics of a navbar
|
|
||||||
@navbar-height: 50px;
|
|
||||||
@navbar-margin-bottom: @line-height-computed;
|
|
||||||
@navbar-border-radius: @border-radius-base;
|
|
||||||
@navbar-padding-horizontal: floor((@grid-gutter-width / 2));
|
|
||||||
@navbar-padding-vertical: ((@navbar-height - @line-height-computed) / 2);
|
|
||||||
@navbar-collapse-max-height: 340px;
|
|
||||||
|
|
||||||
@navbar-default-color: @ps-nav-text;
|
|
||||||
@navbar-default-bg: @ps-nav-bg;
|
|
||||||
@navbar-default-border: darken(@navbar-default-bg, 6.5%);
|
|
||||||
|
|
||||||
// Navbar links
|
|
||||||
@navbar-default-link-color: @navbar-default-color;
|
|
||||||
@navbar-default-link-hover-color: lighten(@navbar-default-color, 20%);
|
|
||||||
@navbar-default-link-hover-bg: transparent;
|
|
||||||
@navbar-default-link-active-color: @navbar-default-link-color;
|
|
||||||
@navbar-default-link-active-bg: darken(@navbar-default-bg, 6.5%);
|
|
||||||
@navbar-default-link-disabled-color: desaturate(@navbar-default-color, 50%);
|
|
||||||
@navbar-default-link-disabled-bg: transparent;
|
|
||||||
|
|
||||||
// Navbar brand label
|
|
||||||
@navbar-default-brand-color: @navbar-default-link-color;
|
|
||||||
@navbar-default-brand-hover-color: darken(@navbar-default-brand-color, 10%);
|
|
||||||
@navbar-default-brand-hover-bg: transparent;
|
|
||||||
|
|
||||||
// Navbar toggle
|
|
||||||
@navbar-default-toggle-hover-bg: #ddd;
|
|
||||||
@navbar-default-toggle-icon-bar-bg: #888;
|
|
||||||
@navbar-default-toggle-border-color: #ddd;
|
|
||||||
|
|
||||||
|
|
||||||
//=== Inverted navbar
|
|
||||||
// Reset inverted navbar basics
|
|
||||||
@navbar-inverse-color: @navbar-default-color;
|
|
||||||
@navbar-inverse-bg: @navbar-default-bg;
|
|
||||||
@navbar-inverse-border: darken(@navbar-inverse-bg, 10%);
|
|
||||||
|
|
||||||
// Inverted navbar links
|
|
||||||
@navbar-inverse-link-color: @navbar-default-color;
|
|
||||||
@navbar-inverse-link-hover-color: lighten(@navbar-inverse-link-color, 20%);
|
|
||||||
@navbar-inverse-link-hover-bg: transparent;
|
|
||||||
@navbar-inverse-link-active-color: @navbar-inverse-link-color;
|
|
||||||
@navbar-inverse-link-active-bg: darken(@navbar-inverse-bg, 10%);
|
|
||||||
@navbar-inverse-link-disabled-color: desaturate(@navbar-inverse-link-color, 50%);
|
|
||||||
@navbar-inverse-link-disabled-bg: transparent;
|
|
||||||
|
|
||||||
// Inverted navbar brand label
|
|
||||||
@navbar-inverse-brand-color: @navbar-inverse-link-color;
|
|
||||||
@navbar-inverse-brand-hover-color: @navbar-inverse-link-hover-color;
|
|
||||||
@navbar-inverse-brand-hover-bg: transparent;
|
|
||||||
|
|
||||||
// Inverted navbar toggle
|
|
||||||
@navbar-inverse-toggle-hover-bg: #333;
|
|
||||||
@navbar-inverse-toggle-icon-bar-bg: #fff;
|
|
||||||
@navbar-inverse-toggle-border-color: #333;
|
|
||||||
|
|
||||||
|
|
||||||
//== Navs
|
|
||||||
//
|
|
||||||
//##
|
|
||||||
|
|
||||||
//=== Shared nav styles
|
|
||||||
@nav-link-padding: 10px 15px;
|
|
||||||
@nav-link-hover-bg: @gray-lighter;
|
|
||||||
|
|
||||||
@nav-disabled-link-color: @gray-light;
|
|
||||||
@nav-disabled-link-hover-color: @gray-light;
|
|
||||||
|
|
||||||
//== Tabs
|
|
||||||
@nav-tabs-border-color: #ddd;
|
|
||||||
|
|
||||||
@nav-tabs-link-hover-border-color: @gray-lighter;
|
|
||||||
|
|
||||||
@nav-tabs-active-link-hover-bg: @body-bg;
|
|
||||||
@nav-tabs-active-link-hover-color: @gray;
|
|
||||||
@nav-tabs-active-link-hover-border-color: #ddd;
|
|
||||||
|
|
||||||
@nav-tabs-justified-link-border-color: #ddd;
|
|
||||||
@nav-tabs-justified-active-link-border-color: @body-bg;
|
|
||||||
|
|
||||||
//== Pills
|
|
||||||
@nav-pills-border-radius: @border-radius-base;
|
|
||||||
@nav-pills-active-link-hover-bg: @component-active-bg;
|
|
||||||
@nav-pills-active-link-hover-color: @component-active-color;
|
|
||||||
|
|
||||||
|
|
||||||
//== Pagination
|
|
||||||
//
|
|
||||||
//##
|
|
||||||
|
|
||||||
@pagination-color: @link-color;
|
|
||||||
@pagination-bg: #fff;
|
|
||||||
@pagination-border: #ddd;
|
|
||||||
|
|
||||||
@pagination-hover-color: @link-hover-color;
|
|
||||||
@pagination-hover-bg: @gray-lighter;
|
|
||||||
@pagination-hover-border: #ddd;
|
|
||||||
|
|
||||||
@pagination-active-color: #fff;
|
|
||||||
@pagination-active-bg: @brand-primary;
|
|
||||||
@pagination-active-border: @brand-primary;
|
|
||||||
|
|
||||||
@pagination-disabled-color: @gray-light;
|
|
||||||
@pagination-disabled-bg: #fff;
|
|
||||||
@pagination-disabled-border: #ddd;
|
|
||||||
|
|
||||||
|
|
||||||
//== Pager
|
|
||||||
//
|
|
||||||
//##
|
|
||||||
|
|
||||||
@pager-bg: @pagination-bg;
|
|
||||||
@pager-border: @pagination-border;
|
|
||||||
@pager-border-radius: 15px;
|
|
||||||
|
|
||||||
@pager-hover-bg: @pagination-hover-bg;
|
|
||||||
|
|
||||||
@pager-active-bg: @pagination-active-bg;
|
|
||||||
@pager-active-color: @pagination-active-color;
|
|
||||||
|
|
||||||
@pager-disabled-color: @pagination-disabled-color;
|
|
||||||
|
|
||||||
|
|
||||||
//== Jumbotron
|
|
||||||
//
|
|
||||||
//##
|
|
||||||
|
|
||||||
@jumbotron-padding: 30px;
|
|
||||||
@jumbotron-color: inherit;
|
|
||||||
@jumbotron-bg: @ps-jumbotron-bg;
|
|
||||||
@jumbotron-heading-color: inherit;
|
|
||||||
@jumbotron-font-size: ceil((@font-size-base * 1.5));
|
|
||||||
@jumbotron-heading-font-size: ceil((@font-size-base * 4.5));
|
|
||||||
|
|
||||||
|
|
||||||
//== Form states and alerts
|
|
||||||
//
|
|
||||||
//## Define colors for form feedback states and, by default, alerts.
|
|
||||||
|
|
||||||
@state-success-text: #3c763d;
|
|
||||||
@state-success-bg: #dff0d8;
|
|
||||||
@state-success-border: darken(spin(@state-success-bg, -10), 5%);
|
|
||||||
|
|
||||||
@state-info-text: #31708f;
|
|
||||||
@state-info-bg: #d9edf7;
|
|
||||||
@state-info-border: darken(spin(@state-info-bg, -10), 7%);
|
|
||||||
|
|
||||||
@state-warning-text: #8a6d3b;
|
|
||||||
@state-warning-bg: #fcf8e3;
|
|
||||||
@state-warning-border: darken(spin(@state-warning-bg, -10), 5%);
|
|
||||||
|
|
||||||
@state-danger-text: #a94442;
|
|
||||||
@state-danger-bg: #f2dede;
|
|
||||||
@state-danger-border: darken(spin(@state-danger-bg, -10), 5%);
|
|
||||||
|
|
||||||
|
|
||||||
//== Tooltips
|
|
||||||
//
|
|
||||||
//##
|
|
||||||
|
|
||||||
//** Tooltip max width
|
|
||||||
@tooltip-max-width: 200px;
|
|
||||||
//** Tooltip text color
|
|
||||||
@tooltip-color: #fff;
|
|
||||||
//** Tooltip background color
|
|
||||||
@tooltip-bg: #000;
|
|
||||||
@tooltip-opacity: .9;
|
|
||||||
|
|
||||||
//** Tooltip arrow width
|
|
||||||
@tooltip-arrow-width: 5px;
|
|
||||||
//** Tooltip arrow color
|
|
||||||
@tooltip-arrow-color: @tooltip-bg;
|
|
||||||
|
|
||||||
|
|
||||||
//== Popovers
|
|
||||||
//
|
|
||||||
//##
|
|
||||||
|
|
||||||
//** Popover body background color
|
|
||||||
@popover-bg: #fff;
|
|
||||||
//** Popover maximum width
|
|
||||||
@popover-max-width: 276px;
|
|
||||||
//** Popover border color
|
|
||||||
@popover-border-color: rgba(0,0,0,.2);
|
|
||||||
//** Popover fallback border color
|
|
||||||
@popover-fallback-border-color: #ccc;
|
|
||||||
|
|
||||||
//** Popover title background color
|
|
||||||
@popover-title-bg: darken(@popover-bg, 3%);
|
|
||||||
|
|
||||||
//** Popover arrow width
|
|
||||||
@popover-arrow-width: 10px;
|
|
||||||
//** Popover arrow color
|
|
||||||
@popover-arrow-color: @popover-bg;
|
|
||||||
|
|
||||||
//** Popover outer arrow width
|
|
||||||
@popover-arrow-outer-width: (@popover-arrow-width + 1);
|
|
||||||
//** Popover outer arrow color
|
|
||||||
@popover-arrow-outer-color: fadein(@popover-border-color, 5%);
|
|
||||||
//** Popover outer arrow fallback color
|
|
||||||
@popover-arrow-outer-fallback-color: darken(@popover-fallback-border-color, 20%);
|
|
||||||
|
|
||||||
|
|
||||||
//== Labels
|
|
||||||
//
|
|
||||||
//##
|
|
||||||
|
|
||||||
//** Default label background color
|
|
||||||
@label-default-bg: @gray-light;
|
|
||||||
//** Primary label background color
|
|
||||||
@label-primary-bg: @brand-primary;
|
|
||||||
//** Success label background color
|
|
||||||
@label-success-bg: @brand-success;
|
|
||||||
//** Info label background color
|
|
||||||
@label-info-bg: @brand-info;
|
|
||||||
//** Warning label background color
|
|
||||||
@label-warning-bg: @brand-warning;
|
|
||||||
//** Danger label background color
|
|
||||||
@label-danger-bg: @brand-danger;
|
|
||||||
|
|
||||||
//** Default label text color
|
|
||||||
@label-color: #fff;
|
|
||||||
//** Default text color of a linked label
|
|
||||||
@label-link-hover-color: #fff;
|
|
||||||
|
|
||||||
|
|
||||||
//== Modals
|
|
||||||
//
|
|
||||||
//##
|
|
||||||
|
|
||||||
//** Padding applied to the modal body
|
|
||||||
@modal-inner-padding: 15px;
|
|
||||||
|
|
||||||
//** Padding applied to the modal title
|
|
||||||
@modal-title-padding: 15px;
|
|
||||||
//** Modal title line-height
|
|
||||||
@modal-title-line-height: @line-height-base;
|
|
||||||
|
|
||||||
//** Background color of modal content area
|
|
||||||
@modal-content-bg: #fff;
|
|
||||||
//** Modal content border color
|
|
||||||
@modal-content-border-color: rgba(0,0,0,.2);
|
|
||||||
//** Modal content border color **for IE8**
|
|
||||||
@modal-content-fallback-border-color: #999;
|
|
||||||
|
|
||||||
//** Modal backdrop background color
|
|
||||||
@modal-backdrop-bg: #000;
|
|
||||||
//** Modal backdrop opacity
|
|
||||||
@modal-backdrop-opacity: .5;
|
|
||||||
//** Modal header border color
|
|
||||||
@modal-header-border-color: #e5e5e5;
|
|
||||||
//** Modal footer border color
|
|
||||||
@modal-footer-border-color: @modal-header-border-color;
|
|
||||||
|
|
||||||
@modal-lg: 900px;
|
|
||||||
@modal-md: 600px;
|
|
||||||
@modal-sm: 300px;
|
|
||||||
|
|
||||||
|
|
||||||
//== Alerts
|
|
||||||
//
|
|
||||||
//## Define alert colors, border radius, and padding.
|
|
||||||
|
|
||||||
@alert-padding: 15px;
|
|
||||||
@alert-border-radius: @border-radius-base;
|
|
||||||
@alert-link-font-weight: bold;
|
|
||||||
|
|
||||||
@alert-success-bg: @state-success-bg;
|
|
||||||
@alert-success-text: @state-success-text;
|
|
||||||
@alert-success-border: @state-success-border;
|
|
||||||
|
|
||||||
@alert-info-bg: @state-info-bg;
|
|
||||||
@alert-info-text: @state-info-text;
|
|
||||||
@alert-info-border: @state-info-border;
|
|
||||||
|
|
||||||
@alert-warning-bg: @state-warning-bg;
|
|
||||||
@alert-warning-text: @state-warning-text;
|
|
||||||
@alert-warning-border: @state-warning-border;
|
|
||||||
|
|
||||||
@alert-danger-bg: @state-danger-bg;
|
|
||||||
@alert-danger-text: @state-danger-text;
|
|
||||||
@alert-danger-border: @state-danger-border;
|
|
||||||
|
|
||||||
|
|
||||||
//== Progress bars
|
|
||||||
//
|
|
||||||
//##
|
|
||||||
|
|
||||||
//** Background color of the whole progress component
|
|
||||||
@progress-bg: #f5f5f5;
|
|
||||||
//** Progress bar text color
|
|
||||||
@progress-bar-color: #fff;
|
|
||||||
//** Variable for setting rounded corners on progress bar.
|
|
||||||
@progress-border-radius: @border-radius-base;
|
|
||||||
|
|
||||||
//** Default progress bar color
|
|
||||||
@progress-bar-bg: @brand-primary;
|
|
||||||
//** Success progress bar color
|
|
||||||
@progress-bar-success-bg: @brand-success;
|
|
||||||
//** Warning progress bar color
|
|
||||||
@progress-bar-warning-bg: @brand-warning;
|
|
||||||
//** Danger progress bar color
|
|
||||||
@progress-bar-danger-bg: @brand-danger;
|
|
||||||
//** Info progress bar color
|
|
||||||
@progress-bar-info-bg: @brand-info;
|
|
||||||
|
|
||||||
|
|
||||||
//== List group
|
|
||||||
//
|
|
||||||
//##
|
|
||||||
|
|
||||||
//** Background color on `.list-group-item`
|
|
||||||
@list-group-bg: #fff;
|
|
||||||
//** `.list-group-item` border color
|
|
||||||
@list-group-border: #ddd;
|
|
||||||
//** List group border radius
|
|
||||||
@list-group-border-radius: @border-radius-base;
|
|
||||||
|
|
||||||
//** Background color of single list items on hover
|
|
||||||
@list-group-hover-bg: #f5f5f5;
|
|
||||||
//** Text color of active list items
|
|
||||||
@list-group-active-color: @component-active-color;
|
|
||||||
//** Background color of active list items
|
|
||||||
@list-group-active-bg: @component-active-bg;
|
|
||||||
//** Border color of active list elements
|
|
||||||
@list-group-active-border: @list-group-active-bg;
|
|
||||||
//** Text color for content within active list items
|
|
||||||
@list-group-active-text-color: lighten(@list-group-active-bg, 40%);
|
|
||||||
|
|
||||||
//** Text color of disabled list items
|
|
||||||
@list-group-disabled-color: @gray-light;
|
|
||||||
//** Background color of disabled list items
|
|
||||||
@list-group-disabled-bg: @gray-lighter;
|
|
||||||
//** Text color for content within disabled list items
|
|
||||||
@list-group-disabled-text-color: @list-group-disabled-color;
|
|
||||||
|
|
||||||
@list-group-link-color: #555;
|
|
||||||
@list-group-link-hover-color: @list-group-link-color;
|
|
||||||
@list-group-link-heading-color: #333;
|
|
||||||
|
|
||||||
|
|
||||||
//== Panels
|
|
||||||
//
|
|
||||||
//##
|
|
||||||
|
|
||||||
@panel-bg: @ps-bg;
|
|
||||||
@panel-body-padding: 15px;
|
|
||||||
@panel-heading-padding: 10px 15px;
|
|
||||||
@panel-footer-padding: @panel-heading-padding;
|
|
||||||
@panel-border-radius: @border-radius-base;
|
|
||||||
|
|
||||||
//** Border color for elements within panels
|
|
||||||
@panel-inner-border: #ddd;
|
|
||||||
@panel-footer-bg: @ps-well-bg;
|
|
||||||
|
|
||||||
@panel-default-text: @ps-text;
|
|
||||||
@panel-default-border: #ddd;
|
|
||||||
@panel-default-heading-bg: @ps-well-bg;
|
|
||||||
|
|
||||||
@panel-primary-text: #fff;
|
|
||||||
@panel-primary-border: @brand-primary;
|
|
||||||
@panel-primary-heading-bg: @brand-primary;
|
|
||||||
|
|
||||||
@panel-success-text: @state-success-text;
|
|
||||||
@panel-success-border: @state-success-border;
|
|
||||||
@panel-success-heading-bg: @state-success-bg;
|
|
||||||
|
|
||||||
@panel-info-text: @state-info-text;
|
|
||||||
@panel-info-border: @state-info-border;
|
|
||||||
@panel-info-heading-bg: @state-info-bg;
|
|
||||||
|
|
||||||
@panel-warning-text: @state-warning-text;
|
|
||||||
@panel-warning-border: @state-warning-border;
|
|
||||||
@panel-warning-heading-bg: @state-warning-bg;
|
|
||||||
|
|
||||||
@panel-danger-text: @state-danger-text;
|
|
||||||
@panel-danger-border: @state-danger-border;
|
|
||||||
@panel-danger-heading-bg: @state-danger-bg;
|
|
||||||
|
|
||||||
|
|
||||||
//== Thumbnails
|
|
||||||
//
|
|
||||||
//##
|
|
||||||
|
|
||||||
//** Padding around the thumbnail image
|
|
||||||
@thumbnail-padding: 4px;
|
|
||||||
//** Thumbnail background color
|
|
||||||
@thumbnail-bg: @body-bg;
|
|
||||||
//** Thumbnail border color
|
|
||||||
@thumbnail-border: #ddd;
|
|
||||||
//** Thumbnail border radius
|
|
||||||
@thumbnail-border-radius: @border-radius-base;
|
|
||||||
|
|
||||||
//** Custom text color for thumbnail captions
|
|
||||||
@thumbnail-caption-color: @text-color;
|
|
||||||
//** Padding around the thumbnail caption
|
|
||||||
@thumbnail-caption-padding: 9px;
|
|
||||||
|
|
||||||
|
|
||||||
//== Wells
|
|
||||||
//
|
|
||||||
//##
|
|
||||||
|
|
||||||
@well-bg: @ps-well-bg;
|
|
||||||
@well-border: darken(@well-bg, 7%);
|
|
||||||
|
|
||||||
|
|
||||||
//== Badges
|
|
||||||
//
|
|
||||||
//##
|
|
||||||
|
|
||||||
@badge-color: #fff;
|
|
||||||
//** Linked badge text color on hover
|
|
||||||
@badge-link-hover-color: #fff;
|
|
||||||
@badge-bg: @gray-light;
|
|
||||||
|
|
||||||
//** Badge text color in active nav link
|
|
||||||
@badge-active-color: @link-color;
|
|
||||||
//** Badge background color in active nav link
|
|
||||||
@badge-active-bg: #fff;
|
|
||||||
|
|
||||||
@badge-font-weight: bold;
|
|
||||||
@badge-line-height: 1;
|
|
||||||
@badge-border-radius: 10px;
|
|
||||||
|
|
||||||
|
|
||||||
//== Breadcrumbs
|
|
||||||
//
|
|
||||||
//##
|
|
||||||
|
|
||||||
@breadcrumb-padding-vertical: 8px;
|
|
||||||
@breadcrumb-padding-horizontal: 15px;
|
|
||||||
//** Breadcrumb background color
|
|
||||||
@breadcrumb-bg: #f5f5f5;
|
|
||||||
//** Breadcrumb text color
|
|
||||||
@breadcrumb-color: #ccc;
|
|
||||||
//** Text color of current page in the breadcrumb
|
|
||||||
@breadcrumb-active-color: @gray-light;
|
|
||||||
//** Textual separator for between breadcrumb elements
|
|
||||||
@breadcrumb-separator: "/";
|
|
||||||
|
|
||||||
|
|
||||||
//== Carousel
|
|
||||||
//
|
|
||||||
//##
|
|
||||||
|
|
||||||
@carousel-text-shadow: 0 1px 2px rgba(0,0,0,.6);
|
|
||||||
|
|
||||||
@carousel-control-color: #fff;
|
|
||||||
@carousel-control-width: 15%;
|
|
||||||
@carousel-control-opacity: .5;
|
|
||||||
@carousel-control-font-size: 20px;
|
|
||||||
|
|
||||||
@carousel-indicator-active-bg: #fff;
|
|
||||||
@carousel-indicator-border-color: #fff;
|
|
||||||
|
|
||||||
@carousel-caption-color: #fff;
|
|
||||||
|
|
||||||
|
|
||||||
//== Close
|
|
||||||
//
|
|
||||||
//##
|
|
||||||
|
|
||||||
@close-font-weight: bold;
|
|
||||||
@close-color: #000;
|
|
||||||
@close-text-shadow: 0 1px 0 #fff;
|
|
||||||
|
|
||||||
|
|
||||||
//== Code
|
|
||||||
//
|
|
||||||
//##
|
|
||||||
|
|
||||||
@code-color: #c7254e;
|
|
||||||
@code-bg: #f9f2f4;
|
|
||||||
|
|
||||||
@kbd-color: #fff;
|
|
||||||
@kbd-bg: #333;
|
|
||||||
|
|
||||||
@pre-bg: #f5f5f5;
|
|
||||||
@pre-color: @gray-dark;
|
|
||||||
@pre-border-color: #ccc;
|
|
||||||
@pre-scrollable-max-height: 340px;
|
|
||||||
|
|
||||||
|
|
||||||
//== Type
|
|
||||||
//
|
|
||||||
//##
|
|
||||||
|
|
||||||
//** Horizontal offset for forms and lists.
|
|
||||||
@component-offset-horizontal: 180px;
|
|
||||||
//** Text muted color
|
|
||||||
@text-muted: @gray-light;
|
|
||||||
//** Abbreviations and acronyms border color
|
|
||||||
@abbr-border-color: @gray-light;
|
|
||||||
//** Headings small color
|
|
||||||
@headings-small-color: @gray-light;
|
|
||||||
//** Blockquote small color
|
|
||||||
@blockquote-small-color: @gray-light;
|
|
||||||
//** Blockquote font size
|
|
||||||
@blockquote-font-size: (@font-size-base * 1.25);
|
|
||||||
//** Blockquote border color
|
|
||||||
@blockquote-border-color: @gray-lighter;
|
|
||||||
//** Page header border color
|
|
||||||
@page-header-border-color: @gray-lighter;
|
|
||||||
//** Width of horizontal description list titles
|
|
||||||
@dl-horizontal-offset: @component-offset-horizontal;
|
|
||||||
//** Point at which .dl-horizontal becomes horizontal
|
|
||||||
@dl-horizontal-breakpoint: @grid-float-breakpoint;
|
|
||||||
//** Horizontal line color.
|
|
||||||
@hr-border: @ps-jumbotron-bg;
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,12 +1,10 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<!-- http://paintstrap.com/preview_by_id/27826?design=large -->
|
|
||||||
<!-- http://www.colourlovers.com/palette/4657935 -->
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
|
||||||
<title>{{ .static.WebsiteTitle }} - Admin</title>
|
<title>{{ .Static.WebsiteTitle }} - Admin</title>
|
||||||
<meta name="description" content="{{ .static.WebsiteTitle }}">
|
<meta name="description" content="{{ .Static.WebsiteTitle }}">
|
||||||
<link rel="stylesheet" href="/css/bootstrap.min.css">
|
<link rel="stylesheet" href="/css/bootstrap.min.css">
|
||||||
<!--link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i"-->
|
<!--link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i"-->
|
||||||
<link rel="stylesheet" href="/fonts/fontawesome-all.min.css">
|
<link rel="stylesheet" href="/fonts/fontawesome-all.min.css">
|
||||||
|
@ -16,38 +14,88 @@
|
||||||
<body id="page-top">
|
<body id="page-top">
|
||||||
{{template "prt_nav.html" .}}
|
{{template "prt_nav.html" .}}
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="page-header">
|
<h1>WireGuard VPN Administration</h1>
|
||||||
<h1>WireGuard VPN Administration</h1>
|
|
||||||
</div>
|
<div class="card">
|
||||||
<div class="panel panel-primary">
|
<div class="card-header">
|
||||||
<div class="panel-heading">
|
<div class="d-flex align-items-center">
|
||||||
<h3 class="panel-title">Interface status for <strong>{{.interface.Name}}</strong></h3>
|
<span class="mr-auto">Interface status for <strong>{{.Device.DeviceName}}</strong></span>
|
||||||
|
<a href="/admin/device/edit"><i class="fas fa-cog"></i></a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="card-body">
|
||||||
<p>Public Key: <strong>{{.interface.PublicKey}}</strong></p>
|
<div class="row">
|
||||||
<p>Listening Port: <strong>{{.interface.ListenPort}}</strong></p>
|
<div class="col-sm-6">
|
||||||
<p>Number of Peers: <strong>{{len .interface.Peers}}</strong></p>
|
<table class="table table-sm table-borderless device-status-table">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>Public Key:</td>
|
||||||
|
<td>{{.Device.PublicKey}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Public Endpoint:</td>
|
||||||
|
<td>{{.Device.Endpoint}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Listening Port:</td>
|
||||||
|
<td>{{.Device.ListenPort}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Enabled Peers:</td>
|
||||||
|
<td>{{len .Device.Interface.Peers}}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<table class="table table-sm table-borderless device-status-table">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>IP Address:</td>
|
||||||
|
<td>{{.Device.IPsStr}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Default allowed IP's:</td>
|
||||||
|
<td>{{.Device.AllowedIPsStr}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Default DNS servers:</td>
|
||||||
|
<td>{{.Device.DNSStr}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Default MTU:</td>
|
||||||
|
<td>{{.Device.Mtu}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Default Keepalive Interval:</td>
|
||||||
|
<td>{{.Device.PersistentKeepalive}}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<hr>
|
<div></div>
|
||||||
<h2>Current VPN Users</h2>
|
<h2>Current VPN Users</h2>
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table class="table table-hover" id="userTable">
|
<table class="table table-sm" id="userTable">
|
||||||
<thead>
|
<thead>
|
||||||
<tr class="d-flex">
|
<tr>
|
||||||
<th scope="col" class="list-image-cell"></th><!-- Status and expand -->
|
<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=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=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=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=ip">IP's <i class="fa fa-fw {{.Session.GetSortIcon "ip"}}"></i></a></th>
|
||||||
<th scope="col"><a href="?sort=traffic">Traffic <i class="fa fa-fw {{.session.GetSortIcon "traffic"}}"></i></a></th>
|
<th scope="col"><a href="?sort=traffic">Traffic <i class="fa fa-fw {{.Session.GetSortIcon "traffic"}}"></i></a></th>
|
||||||
<th scope="col"><a href="?sort=handshake">Last Handshake <i class="fa fa-fw {{.session.GetSortIcon "handshake"}}"></i></a></th>
|
<th scope="col"><a href="?sort=handshake">Last Handshake <i class="fa fa-fw {{.Session.GetSortIcon "handshake"}}"></i></a></th>
|
||||||
<th scope="col"></th><!-- Actions -->
|
<th scope="col"></th><!-- Actions -->
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{{range $i, $p :=.peers}}
|
{{range $i, $p :=.Peers}}
|
||||||
<tr class="d-flex" id="user-pos-{{$i}}">
|
<tr id="user-pos-{{$i}}">
|
||||||
<th scope="row" class="list-image-cell">
|
<th scope="row" class="list-image-cell">
|
||||||
<a href="#{{$p.UID}}" data-toggle="collapse" class="collapse-indicator collapsed"></a>
|
<a href="#{{$p.UID}}" data-toggle="collapse" class="collapse-indicator collapsed"></a>
|
||||||
<!-- online check -->
|
<!-- online check -->
|
||||||
|
@ -59,7 +107,7 @@
|
||||||
<td>{{$p.Peer.ReceiveBytes}} / {{$p.Peer.TransmitBytes}}</td>
|
<td>{{$p.Peer.ReceiveBytes}} / {{$p.Peer.TransmitBytes}}</td>
|
||||||
<td>{{$p.Peer.LastHandshakeTime}}</td>
|
<td>{{$p.Peer.LastHandshakeTime}}</td>
|
||||||
<td>
|
<td>
|
||||||
{{if eq $.session.IsAdmin true}}
|
{{if eq $.Session.IsAdmin true}}
|
||||||
<a href="/admin/user/edit?pos={{$i}}"><i class="fas fa-cog"></i></a>
|
<a href="/admin/user/edit?pos={{$i}}"><i class="fas fa-cog"></i></a>
|
||||||
{{end}}
|
{{end}}
|
||||||
</td>
|
</td>
|
||||||
|
@ -69,38 +117,35 @@
|
||||||
<div class="collapse" id="{{$p.UID}}" data-parent="#userTable">
|
<div class="collapse" id="{{$p.UID}}" data-parent="#userTable">
|
||||||
<div class="row collapsedRow">
|
<div class="row collapsedRow">
|
||||||
<div class="col-md-6 leftBorder">
|
<div class="col-md-6 leftBorder">
|
||||||
<div class="nav btn-group" id="pills-tab{{$p.UID}}" role="tablist">
|
<ul class="nav nav-tabs">
|
||||||
<a data-toggle="tab" href="#t1{{$p.UID}}" class="btn active">General</a>
|
<li class="nav-item">
|
||||||
<a data-toggle="tab" href="#t2{{$p.UID}}" class="btn">Organization</a>
|
<a class="nav-link active" data-toggle="tab" href="#t1{{$p.UID}}">General</a>
|
||||||
<a data-toggle="tab" href="#t3{{$p.UID}}" class="btn">Address</a>
|
</li>
|
||||||
<a data-toggle="tab" href="#t4{{$p.UID}}" class="btn">Telephone</a>
|
<li class="nav-item">
|
||||||
</div>
|
<a class="nav-link" data-toggle="tab" href="#t2{{$p.UID}}">Configuration</a>
|
||||||
|
</li>
|
||||||
<div class="tab-content" id="pills-tabContent{{$p.UID}}">
|
<li class="nav-item">
|
||||||
<div id="t1{{$p.UID}}" class="tab-pane active">
|
<a class="nav-link" data-toggle="tab" href="#t3{{$p.UID}}">Other</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<div class="tab-content" id="tabContent{{$p.UID}}">
|
||||||
|
<div id="t1{{$p.UID}}" class="tab-pane fade active show">
|
||||||
<ul>
|
<ul>
|
||||||
<li>0</li>
|
<li>0</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div id="t2{{$p.UID}}" class="tab-pane">
|
<div id="t2{{$p.UID}}" class="tab-pane fade">
|
||||||
<ul>
|
<pre>{{$p.Config}}</pre>
|
||||||
<li>1</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
</div>
|
||||||
<div id="t3{{$p.UID}}" class="tab-pane">
|
<div id="t3{{$p.UID}}" class="tab-pane fade">
|
||||||
<ul>
|
<ul>
|
||||||
<li>2</li>
|
<li>2</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div id="t4{{$p.UID}}" class="tab-pane">
|
|
||||||
<ul>
|
|
||||||
<li>4</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<img class="list-image-large" src="/user/qr.jpg"/>
|
<img class="list-image-large" src="/user/qrcode?pkey={{$p.PublicKey}}"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -109,12 +154,12 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<p>Currently listed peers: <strong>{{len .peers}}</strong></p>
|
<p>Currently listed peers: <strong>{{len .Peers}}</strong></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{template "prt_footer.html"}}
|
{{template "prt_footer.html"}}
|
||||||
<script src="/js/jquery.min.js"></script>
|
<script src="/js/jquery.min.js"></script>
|
||||||
<script src="/js/bootstrap.min.js"></script>
|
<script src="/js/bootstrap.bundle.min.js"></script>
|
||||||
<script src="/js/jquery.easing.js"></script>
|
<script src="/js/jquery.easing.js"></script>
|
||||||
<script src="/js/custom.js"></script>
|
<script src="/js/custom.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -1,57 +1,38 @@
|
||||||
<nav class="navbar navbar-default navbar-fixed-top">
|
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
|
||||||
<div class="container">
|
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#topNavbar" aria-controls="navbarTogglerDemo03" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
<div class="navbar-header">
|
<span class="navbar-toggler-icon"></span>
|
||||||
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
|
</button>
|
||||||
<span class="sr-only">Toggle navigation</span>
|
|
||||||
<span class="icon-bar"></span>
|
<a class="navbar-brand" href="/"><img src="/img/PROLICHT_FULL.png" alt="PROLICHT"/></a>
|
||||||
<span class="icon-bar"></span>
|
<div id="topNavbar" class="navbar-collapse collapse">
|
||||||
<span class="icon-bar"></span>
|
<ul class="navbar-nav mr-auto mt-2 mt-lg-0">
|
||||||
</button>
|
<li class="nav-spacer"></li>
|
||||||
<a class="navbar-brand" href="/"><img src="/img/PROLICHT_FULL.png" alt="PROLICHT"/></a>
|
<form class="form-inline my-2 my-lg-0" action="/search">
|
||||||
</div>
|
<input class="form-control mr-sm-2" name="search" type="search" placeholder="Search" aria-label="Search">
|
||||||
<div id="navbar" class="navbar-collapse collapse">
|
<button class="btn btn-outline-success my-2 my-sm-0" type="submit"><i class="fa fa-search"></i></button>
|
||||||
<ul class="nav navbar-nav">
|
</form>
|
||||||
<li class="nav-spacer"></li>
|
|
||||||
{{with eq $.session.LoggedIn true}}{{with eq $.session.IsAdmin true}}
|
</ul>
|
||||||
<form class="navbar-form navbar-right" action="/">
|
{{if eq $.Session.LoggedIn true}}
|
||||||
<div class="form-group btn-group">
|
<div class="nav-item dropdown">
|
||||||
<input id="inputSearch" name="search" type="search" placeholder="Search..." onsearch="OnSearch(this)" class="form-control" value="{{$.session.Search}}">
|
<a href="#" class="navbar-text dropdown-toggle" data-toggle="dropdown">{{$.Session.Firstname}} {{$.Session.Lastname}} <span class="caret"></span></a>
|
||||||
<!--span id="searchclear"><i class="fas fa-times"></i></span-->
|
<div class="dropdown-menu">
|
||||||
</div>
|
{{with eq $.Session.LoggedIn true}}{{with eq $.Session.IsAdmin true}}
|
||||||
<div class="form-group btn-group">
|
<a class="dropdown-item" href="/admin/"><i class="fas fa-file-export"></i> Administration</a>
|
||||||
<select name="department" id="inputDepartment" type="search" class="form-control">
|
<div class="dropdown-divider"></div>
|
||||||
<option value="">All departments</option>
|
{{end}}{{end}}
|
||||||
{{range $i, $department := $.departments}}
|
<a class="dropdown-item" href="/user/{{$.Session.UserName}}/profile"><i class="fas fa-user"></i> Profile</a>
|
||||||
{{if eq $department $.session.SearchDepartment}}
|
<div class="dropdown-divider"></div>
|
||||||
<option value="{{$department}}" selected>{{$department}}</option>
|
<a class="dropdown-item" href="{{ $.Static.LogoutURL }}"><i class="fas fa-sign-out-alt"></i> Logout</a>
|
||||||
{{else}}
|
</div>
|
||||||
<option value="{{$department}}">{{$department}}</option>
|
</div>
|
||||||
{{end}}
|
{{else}}
|
||||||
{{end}}
|
<a href="{{ $.Static.LoginURL }}" class="navbar-text"><i class="fas fa-sign-in-alt fa-sm fa-fw mr-2 text-gray-400"></i> Login</a></li>
|
||||||
</select>
|
{{end}}
|
||||||
</div>
|
</div><!--/.navbar-collapse -->
|
||||||
<button type="submit" class="btn btn-outline-light"><i class="fa fa-search"></i></button>
|
</nav>
|
||||||
</form>
|
{{if not $.Device.IsValid}}
|
||||||
{{end}}{{end}}
|
<div class="container">
|
||||||
</ul>
|
<div class="alert alert-danger">Warning: WireGuard Interface is not fully configured! Configurations may be incomplete and non functional!</div>
|
||||||
<ul class="nav navbar-nav navbar-right">
|
</div>
|
||||||
{{if eq $.session.LoggedIn true}}
|
{{end}}
|
||||||
<li class="dropdown">
|
|
||||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">{{$.session.Firstname}} {{$.session.Lastname}} <span class="caret"></span></a>
|
|
||||||
<ul class="dropdown-menu">
|
|
||||||
{{with eq $.session.LoggedIn true}}{{with eq $.session.IsAdmin true}}
|
|
||||||
<li><a href="/admin/"><i class="fas fa-file-export"></i> Administration</a></li>
|
|
||||||
<li role="separator" class="divider"></li>
|
|
||||||
{{end}}{{end}}
|
|
||||||
<li><a href="/user/{{$.session.UserName}}/profile"><i class="fas fa-user"></i> Profile</a></li>
|
|
||||||
<li role="separator" class="divider"></li>
|
|
||||||
<li><a href="{{ $.static.LogoutURL }}"><i class="fas fa-sign-out-alt"></i> Logout</a></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
{{else}}
|
|
||||||
<li><a href="{{ $.static.LoginURL }}"><i class="fas fa-sign-in-alt fa-sm fa-fw mr-2 text-gray-400"></i> Login</a></li>
|
|
||||||
{{end}}
|
|
||||||
</ul>
|
|
||||||
</div><!--/.navbar-collapse -->
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
1
go.mod
1
go.mod
|
@ -10,6 +10,7 @@ require (
|
||||||
github.com/gorilla/sessions v1.2.1 // indirect
|
github.com/gorilla/sessions v1.2.1 // indirect
|
||||||
github.com/kelseyhightower/envconfig v1.4.0
|
github.com/kelseyhightower/envconfig v1.4.0
|
||||||
github.com/sirupsen/logrus v1.7.0
|
github.com/sirupsen/logrus v1.7.0
|
||||||
|
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
|
||||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20200609130330-bd2cb7843e1b
|
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20200609130330-bd2cb7843e1b
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c
|
||||||
gorm.io/driver/sqlite v1.1.3
|
gorm.io/driver/sqlite v1.1.3
|
||||||
|
|
2
go.sum
2
go.sum
|
@ -72,6 +72,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM=
|
github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM=
|
||||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||||
|
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
|
||||||
|
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
|
|
@ -43,15 +43,35 @@ func (s *Server) GetAdminIndex(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
device := s.users.GetDevice()
|
||||||
|
device.Interface = dev
|
||||||
|
|
||||||
users := make([]User, len(peers))
|
users := make([]User, len(peers))
|
||||||
for i, peer := range peers {
|
for i, peer := range peers {
|
||||||
users[i] = s.users.GetOrCreateUserForPeer(peer)
|
users[i] = s.users.GetOrCreateUserForPeer(peer)
|
||||||
}
|
}
|
||||||
c.HTML(http.StatusOK, "admin_index.html", gin.H{
|
c.HTML(http.StatusOK, "admin_index.html", struct {
|
||||||
"route": c.Request.URL.Path,
|
Route string
|
||||||
"session": s.getSessionData(c),
|
Session SessionData
|
||||||
"static": s.getStaticData(),
|
Static StaticData
|
||||||
"peers": users,
|
Peers []User
|
||||||
"interface": dev,
|
Device Device
|
||||||
|
}{
|
||||||
|
Route: c.Request.URL.Path,
|
||||||
|
Session: s.getSessionData(c),
|
||||||
|
Static: s.getStaticData(),
|
||||||
|
Peers: users,
|
||||||
|
Device: device,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Server) GetUserQRCode(c *gin.Context) {
|
||||||
|
user := s.users.GetUser(c.Param("pkey"))
|
||||||
|
png, err := user.GetQRCode()
|
||||||
|
if err != nil {
|
||||||
|
s.HandleError(c, http.StatusInternalServerError, "QRCode error", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.Data(http.StatusOK, "image/png", png)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ func SetupRoutes(s *Server) {
|
||||||
// User routes
|
// User routes
|
||||||
user := s.server.Group("/user")
|
user := s.server.Group("/user")
|
||||||
user.Use(s.RequireAuthentication("")) // empty scope = all logged in users
|
user.Use(s.RequireAuthentication("")) // empty scope = all logged in users
|
||||||
|
user.GET("/qrcode", s.GetUserQRCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) RequireAuthentication(scope string) gin.HandlerFunc {
|
func (s *Server) RequireAuthentication(scope string) gin.HandlerFunc {
|
||||||
|
|
|
@ -1,25 +1,31 @@
|
||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
|
"text/template"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/h44z/wg-portal/internal/wireguard"
|
||||||
|
|
||||||
"github.com/h44z/wg-portal/internal/common"
|
"github.com/h44z/wg-portal/internal/common"
|
||||||
|
|
||||||
"github.com/h44z/wg-portal/internal/ldap"
|
"github.com/h44z/wg-portal/internal/ldap"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
"github.com/skip2/go-qrcode"
|
||||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||||
"gorm.io/driver/sqlite"
|
"gorm.io/driver/sqlite"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
type User struct {
|
type User struct {
|
||||||
Peer wgtypes.Peer `gorm:"-"`
|
Peer wgtypes.Peer `gorm:"-"`
|
||||||
User *ldap.UserCacheHolderEntry `gorm:"-"` // optional, it is still possible to have users without ldap
|
User *ldap.UserCacheHolderEntry `gorm:"-"` // optional, it is still possible to have users without ldap
|
||||||
|
Config string `gorm:"-"`
|
||||||
|
|
||||||
UID string // uid for html identification
|
UID string // uid for html identification
|
||||||
IsOnline bool `gorm:"-"`
|
IsOnline bool `gorm:"-"`
|
||||||
|
@ -42,7 +48,7 @@ type User struct {
|
||||||
UpdatedAt time.Time
|
UpdatedAt time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *User) GetPeerConfig() wgtypes.PeerConfig {
|
func (u User) GetPeerConfig() wgtypes.PeerConfig {
|
||||||
publicKey, _ := wgtypes.ParseKey(u.PublicKey)
|
publicKey, _ := wgtypes.ParseKey(u.PublicKey)
|
||||||
var presharedKey *wgtypes.Key
|
var presharedKey *wgtypes.Key
|
||||||
if u.PresharedKey != "" {
|
if u.PresharedKey != "" {
|
||||||
|
@ -70,7 +76,20 @@ func (u *User) GetPeerConfig() wgtypes.PeerConfig {
|
||||||
return cfg
|
return cfg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u User) GetQRCode() ([]byte, error) {
|
||||||
|
png, err := qrcode.Encode(u.Config, qrcode.Medium, 250)
|
||||||
|
if err != nil {
|
||||||
|
log.WithFields(log.Fields{
|
||||||
|
"err": err,
|
||||||
|
}).Error("failed to create qrcode")
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return png, nil
|
||||||
|
}
|
||||||
|
|
||||||
type Device struct {
|
type Device struct {
|
||||||
|
Interface *wgtypes.Device `gorm:"-"`
|
||||||
|
|
||||||
DeviceName string `gorm:"primaryKey"`
|
DeviceName string `gorm:"primaryKey"`
|
||||||
PrivateKey string
|
PrivateKey string
|
||||||
PublicKey string
|
PublicKey string
|
||||||
|
@ -92,7 +111,7 @@ type Device struct {
|
||||||
UpdatedAt time.Time
|
UpdatedAt time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Device) IsValid() bool {
|
func (d Device) IsValid() bool {
|
||||||
if len(d.IPs) == 0 {
|
if len(d.IPs) == 0 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -150,13 +169,15 @@ func (u *UserManager) GetAllUsers() []User {
|
||||||
for i := range users {
|
for i := range users {
|
||||||
users[i].AllowedIPs = strings.Split(users[i].AllowedIPsStr, ", ")
|
users[i].AllowedIPs = strings.Split(users[i].AllowedIPsStr, ", ")
|
||||||
users[i].IPs = strings.Split(users[i].IPsStr, ", ")
|
users[i].IPs = strings.Split(users[i].IPsStr, ", ")
|
||||||
|
tmpCfg, _ := u.GetPeerConfigFile(users[i])
|
||||||
|
users[i].Config = string(tmpCfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
return users
|
return users
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UserManager) GetAllDevices() []Device {
|
func (u *UserManager) GetDevice() Device {
|
||||||
devices := make([]Device, 0)
|
devices := make([]Device, 0, 1)
|
||||||
u.db.Find(&devices)
|
u.db.Find(&devices)
|
||||||
|
|
||||||
for i := range devices {
|
for i := range devices {
|
||||||
|
@ -165,7 +186,7 @@ func (u *UserManager) GetAllDevices() []Device {
|
||||||
devices[i].DNS = strings.Split(devices[i].DNSStr, ", ")
|
devices[i].DNS = strings.Split(devices[i].DNSStr, ", ")
|
||||||
}
|
}
|
||||||
|
|
||||||
return devices
|
return devices[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UserManager) GetOrCreateUserForPeer(peer wgtypes.Peer) User {
|
func (u *UserManager) GetOrCreateUserForPeer(peer wgtypes.Peer) User {
|
||||||
|
@ -199,6 +220,20 @@ func (u *UserManager) GetOrCreateUserForPeer(peer wgtypes.Peer) User {
|
||||||
|
|
||||||
user.IPs = strings.Split(user.IPsStr, ", ")
|
user.IPs = strings.Split(user.IPsStr, ", ")
|
||||||
user.AllowedIPs = strings.Split(user.AllowedIPsStr, ", ")
|
user.AllowedIPs = strings.Split(user.AllowedIPsStr, ", ")
|
||||||
|
tmpCfg, _ := u.GetPeerConfigFile(user)
|
||||||
|
user.Config = string(tmpCfg)
|
||||||
|
|
||||||
|
return user
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *UserManager) GetUser(publicKey string) User {
|
||||||
|
user := User{}
|
||||||
|
u.db.Where("public_key = ?", publicKey).FirstOrInit(&user)
|
||||||
|
|
||||||
|
user.IPs = strings.Split(user.IPsStr, ", ")
|
||||||
|
user.AllowedIPs = strings.Split(user.AllowedIPsStr, ", ")
|
||||||
|
tmpCfg, _ := u.GetPeerConfigFile(user)
|
||||||
|
user.Config = string(tmpCfg)
|
||||||
|
|
||||||
return user
|
return user
|
||||||
}
|
}
|
||||||
|
@ -250,18 +285,16 @@ func (u *UserManager) GetAllReservedIps() ([]string, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
devices := u.GetAllDevices()
|
device := u.GetDevice()
|
||||||
for _, device := range devices {
|
for _, cidr := range device.IPs {
|
||||||
for _, cidr := range device.IPs {
|
ip, _, err := net.ParseCIDR(cidr)
|
||||||
ip, _, err := net.ParseCIDR(cidr)
|
if err != nil {
|
||||||
if err != nil {
|
log.WithFields(log.Fields{
|
||||||
log.WithFields(log.Fields{
|
"err": err,
|
||||||
"err": err,
|
"cidr": cidr,
|
||||||
"cidr": cidr,
|
}).Error("failed to ip from cidr")
|
||||||
}).Error("failed to ip from cidr")
|
} else {
|
||||||
} else {
|
reservedIps = append(reservedIps, ip.String())
|
||||||
reservedIps = append(reservedIps, ip.String())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -320,3 +353,25 @@ func (u *UserManager) GetOrCreateDevice(dev wgtypes.Device) Device {
|
||||||
|
|
||||||
return device
|
return device
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *UserManager) GetPeerConfigFile(user User) ([]byte, error) {
|
||||||
|
tpl, err := template.New("client").Funcs(template.FuncMap{"StringsJoin": strings.Join}).Parse(wireguard.ClientCfgTpl)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var tplBuff bytes.Buffer
|
||||||
|
|
||||||
|
err = tpl.Execute(&tplBuff, struct {
|
||||||
|
Client User
|
||||||
|
Server Device
|
||||||
|
}{
|
||||||
|
Client: user,
|
||||||
|
Server: u.GetDevice(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return tplBuff.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
package wireguard
|
||||||
|
|
||||||
|
var (
|
||||||
|
ClientCfgTpl = `[Interface]
|
||||||
|
Address = {{ .Client.IPsStr }}
|
||||||
|
PrivateKey = {{ .Client.PrivateKey }}
|
||||||
|
{{ if ne (len .Server.DNS) 0 -}}
|
||||||
|
DNS = {{ .Server.DNSStr }}
|
||||||
|
{{- end }}
|
||||||
|
{{ if ne .Server.Mtu 0 -}}
|
||||||
|
MTU = {{.Server.Mtu}}
|
||||||
|
{{- end}}
|
||||||
|
[Peer]
|
||||||
|
PublicKey = {{ .Server.PublicKey }}
|
||||||
|
PresharedKey = {{ .Client.PresharedKey }}
|
||||||
|
AllowedIPs = {{ .Client.AllowedIPsStr }}
|
||||||
|
Endpoint = {{ .Server.Endpoint }}
|
||||||
|
{{ if and (ne .Server.PersistentKeepalive 0) (not .Client.IgnorePersistentKeepalive) -}}
|
||||||
|
PersistentKeepalive = {{.Server.PersistentKeepalive}}
|
||||||
|
{{- end}}
|
||||||
|
`
|
||||||
|
)
|
Loading…
Reference in New Issue