diff --git a/.gitignore b/.gitignore
index 28806e8a..d5b7ce83 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,4 +5,5 @@ tarpaulin-report.html
cobertura.xml
prod/
node_modules/
-static/bundle
+static-assets/bundle
+static
diff --git a/Makefile b/Makefile
index b4309dc6..22407170 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
default: build-frontend
cargo build
-run: build-frontend
+run: build-frontend-dev
cargo run
dev-env:
diff --git a/src/cache_buster_data.json b/src/cache_buster_data.json
index 3710f6db..2bdbdfe8 100644
--- a/src/cache_buster_data.json
+++ b/src/cache_buster_data.json
@@ -1 +1 @@
-{"map":{"./static-assets/img/svg/filter.svg":"./static/img/svg/filter.6D5FBD96BA2E2020663AAC4994A991295917D73F3592C07EE103647B655A2275.svg","./static-assets/img/svg/home.svg":"./static/img/svg/home.28C26C2D3E4013D24D755A589A80D8DD5C49DA5397032E3F09B76BC3A2C314ED.svg","./static-assets/img/svg/shield.svg":"./static/img/svg/shield.13AFE15DCB4882B4A940CFDC3E2088A733CD4E6F97F25B211D87C7C9D6DBA2B6.svg","./static-assets/img/svg/eye.svg":"./static/img/svg/eye.9DE4D24D3C9B055D02B94A8AD65E8C0C644852381FDD131A64448B6DA7859167.svg","./static-assets/img/svg/settings.svg":"./static/img/svg/settings.910C6241743C9C694141971BE8E1C4016A1A5BF203E4E9D676D4CE93BD518F4C.svg","./static-assets/img/svg/message-square.svg":"./static/img/svg/message-square.E246A6B2AAEFCE8A62B9BDD2D155D3B4923C3E48325EAEF099D509A2D7BB4DD1.svg","./static-assets/img/svg/eye-off.svg":"./static/img/svg/eye-off.939360B335D1D35B57C3E2070129D14ABB168E4AC137B5BE4F6F8BD450B712F5.svg","./static-assets/img/svg/toggle-left.svg":"./static/img/svg/toggle-left.E421950C5922E84015F0A86F272AE5637A2ED96E267D2C962543F5994E5D1172.svg","./static-assets/img/svg/user.svg":"./static/img/svg/user.B164ECD2C4A09DC5189F1F252487E2AC6A33646BEA67AF9C528CDA61FE5E146F.svg","./static-assets/img/svg/globe.svg":"./static/img/svg/globe.44C2A069EBD637663E938ECE7B8E4EC2A8BDE049A8A044EC68D9CB69AE8C592E.svg","./static-assets/img/svg/shield-off.svg":"./static/img/svg/shield-off.85394A6AD92D550F8EBA72AAB095E078E7A0E3359DF81174532C8D1AF53B5876.svg","./static-assets/img/svg/tag.svg":"./static/img/svg/tag.E0BC111B8E81BBFC62B6A9E7E4AC162B7085A6543D995B7A0030CB7632901BD4.svg","./static-assets/img/svg/moon.svg":"./static/img/svg/moon.1E151D68949CA3B2DC7DE34BC25B7586E4175AC3BA7F56DDBB34227334EF7155.svg","./static-assets/img/svg/key.svg":"./static/img/svg/key.F0AACBED8D0F7A279977392F92F4DA73C35E905AC73B3C83320D54856E627EEC.svg","./static-assets/img/svg/credit-card.svg":"./static/img/svg/credit-card.DF612AFE367A7B31410F2F6CD3C7B515B0F1889C0107EA695D840DFFA492E07D.svg","./static-assets/img/svg/log-out.svg":"./static/img/svg/log-out.92AB4384FD41D9AFE4735C480361BB64789CD767B7DD0FF3C6F56287B3D4498E.svg","./static-assets/img/svg/bell.svg":"./static/img/svg/bell.9DA292704EE9907EFDB870F4510C97336977CA27FBFAAD83CF46F8E22D3828F7.svg","./static-assets/img/svg/github.svg":"./static/img/svg/github.FA9EB1C66F548EC2C7598B94BA6A17275E1EA383D42B6C83351A2388C773E621.svg","./static-assets/img/svg/menu.svg":"./static/img/svg/menu.A2C4DD00686F5D23F78885AC4CE3E075FCA78DFBDEA70407667FBBD9801B7A75.svg","./static-assets/img/icon.png":"./static/img/icon.CC75A040D5F432E5DC9043D10B94BF1FC3BAE1D02A8C2030F655E642EAD4A32C.png","./static-assets/img/svg/file.svg":"./static/img/svg/file.F9E376D9F78FFD918D8D592A8B2D97EAAC14E638B5A7AE3C58DDB075375D8E0E.svg","./static-assets/bundle/main.js":"./static/bundle/main.47250AD075BB60388779EF82D1C6A084AB82B69A9061D8A4DFCF1C18C07A0C4F.js","./static-assets/bundle/main.css":"./static/bundle/main.C7B0ACE647935B5E61BD692A0EB6AFF167CAB2F80483079378CF7A18D7FF9466.css","./static-assets/img/svg/file-text.svg":"./static/img/svg/file-text.CF57DF252051E7E81C240D36AF1DB8A9DDAF282F9A5E8C338408FE88A6545A02.svg","./static-assets/img/svg/help-circle.svg":"./static/img/svg/help-circle.BE230ABD2E05EB05EF6C5B7D04D35A3A43637EF1E046DEF3D244425609B99F81.svg","./static-assets/img/icon-trans.png":"./static/img/icon-trans.7920418313D84DCDB2491E02E52E4BEF374970C216E85BD721274EE51241ECD4.png","./static-assets/img/svg/toggle-right.svg":"./static/img/svg/toggle-right.15BF49887941593CE3FE09FA73E3CAF1F4B1E8ABCB42A23D85B4FCBC24FDF5AA.svg"},"base_dir":"./static"}
\ No newline at end of file
+{"map":{"./static-assets/img/svg/eye.svg":"./static/img/svg/eye.9DE4D24D3C9B055D02B94A8AD65E8C0C644852381FDD131A64448B6DA7859167.svg","./static-assets/img/svg/message-square.svg":"./static/img/svg/message-square.E246A6B2AAEFCE8A62B9BDD2D155D3B4923C3E48325EAEF099D509A2D7BB4DD1.svg","./static-assets/img/svg/eye-off.svg":"./static/img/svg/eye-off.939360B335D1D35B57C3E2070129D14ABB168E4AC137B5BE4F6F8BD450B712F5.svg","./static-assets/img/svg/toggle-left.svg":"./static/img/svg/toggle-left.E421950C5922E84015F0A86F272AE5637A2ED96E267D2C962543F5994E5D1172.svg","./static-assets/img/icon.png":"./static/img/icon.CC75A040D5F432E5DC9043D10B94BF1FC3BAE1D02A8C2030F655E642EAD4A32C.png","./static-assets/img/svg/moon.svg":"./static/img/svg/moon.1E151D68949CA3B2DC7DE34BC25B7586E4175AC3BA7F56DDBB34227334EF7155.svg","./static-assets/img/svg/key.svg":"./static/img/svg/key.F0AACBED8D0F7A279977392F92F4DA73C35E905AC73B3C83320D54856E627EEC.svg","./static-assets/bundle/main.css":"./static/bundle/main.C5FDAAD302D069CE1344663AFE0BD75A643A34C79FE228714F8C92BDD1827666.css","./static-assets/bundle/main.js":"./static/bundle/main.F1F284AF11A2DF33C55F2263CB65458529E943F04474204EEC973F33053C7F56.js","./static-assets/img/svg/log-out.svg":"./static/img/svg/log-out.92AB4384FD41D9AFE4735C480361BB64789CD767B7DD0FF3C6F56287B3D4498E.svg","./static-assets/img/svg/file.svg":"./static/img/svg/file.F9E376D9F78FFD918D8D592A8B2D97EAAC14E638B5A7AE3C58DDB075375D8E0E.svg","./static-assets/img/svg/globe.svg":"./static/img/svg/globe.44C2A069EBD637663E938ECE7B8E4EC2A8BDE049A8A044EC68D9CB69AE8C592E.svg","./static-assets/img/svg/shield.svg":"./static/img/svg/shield.13AFE15DCB4882B4A940CFDC3E2088A733CD4E6F97F25B211D87C7C9D6DBA2B6.svg","./static-assets/img/svg/toggle-right.svg":"./static/img/svg/toggle-right.15BF49887941593CE3FE09FA73E3CAF1F4B1E8ABCB42A23D85B4FCBC24FDF5AA.svg","./static-assets/img/svg/help-circle.svg":"./static/img/svg/help-circle.BE230ABD2E05EB05EF6C5B7D04D35A3A43637EF1E046DEF3D244425609B99F81.svg","./static-assets/img/svg/home.svg":"./static/img/svg/home.28C26C2D3E4013D24D755A589A80D8DD5C49DA5397032E3F09B76BC3A2C314ED.svg","./static-assets/img/svg/settings.svg":"./static/img/svg/settings.910C6241743C9C694141971BE8E1C4016A1A5BF203E4E9D676D4CE93BD518F4C.svg","./static-assets/img/svg/github.svg":"./static/img/svg/github.FA9EB1C66F548EC2C7598B94BA6A17275E1EA383D42B6C83351A2388C773E621.svg","./static-assets/img/svg/shield-off.svg":"./static/img/svg/shield-off.85394A6AD92D550F8EBA72AAB095E078E7A0E3359DF81174532C8D1AF53B5876.svg","./static-assets/img/svg/file-text.svg":"./static/img/svg/file-text.CF57DF252051E7E81C240D36AF1DB8A9DDAF282F9A5E8C338408FE88A6545A02.svg","./static-assets/img/icon-trans.png":"./static/img/icon-trans.7920418313D84DCDB2491E02E52E4BEF374970C216E85BD721274EE51241ECD4.png","./static-assets/img/svg/credit-card.svg":"./static/img/svg/credit-card.DF612AFE367A7B31410F2F6CD3C7B515B0F1889C0107EA695D840DFFA492E07D.svg","./static-assets/img/svg/user.svg":"./static/img/svg/user.B164ECD2C4A09DC5189F1F252487E2AC6A33646BEA67AF9C528CDA61FE5E146F.svg","./static-assets/img/svg/menu.svg":"./static/img/svg/menu.A2C4DD00686F5D23F78885AC4CE3E075FCA78DFBDEA70407667FBBD9801B7A75.svg","./static-assets/img/svg/bell.svg":"./static/img/svg/bell.9DA292704EE9907EFDB870F4510C97336977CA27FBFAAD83CF46F8E22D3828F7.svg","./static-assets/img/svg/tag.svg":"./static/img/svg/tag.E0BC111B8E81BBFC62B6A9E7E4AC162B7085A6543D995B7A0030CB7632901BD4.svg","./static-assets/img/svg/filter.svg":"./static/img/svg/filter.6D5FBD96BA2E2020663AAC4994A991295917D73F3592C07EE103647B655A2275.svg"},"base_dir":"./static"}
\ No newline at end of file
diff --git a/src/main.rs b/src/main.rs
index 3c9ecc84..a717a84f 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -40,6 +40,8 @@ pub use data::Data;
pub use settings::Settings;
use static_assets::FileMap;
+pub use crate::middleware::auth::CheckLogin;
+
lazy_static! {
pub static ref SETTINGS: Settings = Settings::new().unwrap();
pub static ref S: String = env::var("S").unwrap();
diff --git a/src/templates/mod.rs b/src/templates/mod.rs
index cd7d1c4a..772c76bd 100644
--- a/src/templates/mod.rs
+++ b/src/templates/mod.rs
@@ -20,8 +20,6 @@ use actix_web::web::ServiceConfig;
mod auth;
mod panel;
-pub use crate::middleware::auth::CheckLogin;
-
pub fn services(cfg: &mut ServiceConfig) {
cfg.service(panel::panel);
cfg.service(panel::sitekey::add_sitekey);
@@ -36,18 +34,52 @@ mod tests {
use actix_web::test;
use super::*;
+ use crate::tests::*;
use crate::*;
#[actix_rt::test]
async fn protected_pages_templates_work() {
- let mut app = test::init_service(App::new().configure(services)).await;
+ const NAME: &str = "templateuser";
+ const PASSWORD: &str = "longpassword";
+ const EMAIL: &str = "templateuser@a.com";
+
+ {
+ let data = Data::new().await;
+ delete_user(NAME, &data).await;
+ }
+
+ let (data, _, signin_resp) = register_and_signin(NAME, EMAIL, PASSWORD).await;
+ let cookies = get_cookie!(signin_resp);
+
+ let mut app = test::init_service(
+ App::new()
+ .wrap(get_identity_service())
+ .configure(crate::api::v1::services)
+ .configure(services)
+ .data(data.clone()),
+ )
+ .await;
+
let urls = vec!["/", "/sitekey/add"];
for url in urls.iter() {
let resp =
test::call_service(&mut app, test::TestRequest::get().uri(url).to_request()).await;
assert_eq!(resp.status(), StatusCode::FOUND);
+
+ let authenticated_resp = test::call_service(
+ &mut app,
+ test::TestRequest::get()
+ .uri(url)
+ .cookie(cookies.clone())
+ .to_request(),
+ )
+ .await;
+
+ assert_eq!(authenticated_resp.status(), StatusCode::OK);
}
+
+ delete_user(NAME, &data).await;
}
#[actix_rt::test]
diff --git a/src/templates/panel/mod.rs b/src/templates/panel/mod.rs
index 4bda7c42..1b1bd0aa 100644
--- a/src/templates/panel/mod.rs
+++ b/src/templates/panel/mod.rs
@@ -15,13 +15,10 @@
* along with this program. If not, see .
*/
-use actix_identity::Identity;
-use actix_web::http::header;
use actix_web::{get, HttpResponse, Responder};
use sailfish::TemplateOnce;
-use crate::api::v1::auth::is_authenticated;
-pub use crate::middleware::auth::CheckLogin;
+use crate::CheckLogin;
pub mod sitekey;
@@ -44,13 +41,7 @@ impl<'a> Default for IndexPage<'a> {
}
#[get("/", wrap = "CheckLogin")]
-pub async fn panel(id: Identity) -> impl Responder {
- if is_authenticated(&id).is_err() {
- return HttpResponse::TemporaryRedirect()
- .set_header(header::LOCATION, "/login")
- .body("");
- }
-
+pub async fn panel() -> impl Responder {
let body = IndexPage::default().render_once().unwrap();
HttpResponse::Ok()
.content_type("text/html; charset=utf-8")
diff --git a/src/templates/panel/sitekey.rs b/src/templates/panel/sitekey/add.rs
similarity index 87%
rename from src/templates/panel/sitekey.rs
rename to src/templates/panel/sitekey/add.rs
index fe198454..624249e7 100644
--- a/src/templates/panel/sitekey.rs
+++ b/src/templates/panel/sitekey/add.rs
@@ -18,13 +18,16 @@
use actix_web::{get, HttpResponse, Responder};
use sailfish::TemplateOnce;
-use super::CheckLogin;
+use crate::CheckLogin;
#[derive(TemplateOnce, Clone)]
#[template(path = "panel/add-site-key/index.html")]
pub struct IndexPage<'a> {
pub name: &'a str,
pub title: &'a str,
+ pub levels: usize,
+ pub form_title: &'a str,
+ pub form_description: &'a str,
}
const TITLE: &str = "Add Site Key";
@@ -34,6 +37,9 @@ impl<'a> Default for IndexPage<'a> {
IndexPage {
name: "mCaptcha",
title: TITLE,
+ levels: 1,
+ form_description: "",
+ form_title: "Add Site Key",
}
}
}
diff --git a/src/templates/panel/sitekey/mod.rs b/src/templates/panel/sitekey/mod.rs
new file mode 100644
index 00000000..cf3359c5
--- /dev/null
+++ b/src/templates/panel/sitekey/mod.rs
@@ -0,0 +1,19 @@
+/*
+* Copyright (C) 2021 Aravinth Manivannan
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Affero General Public License as
+* published by the Free Software Foundation, either version 3 of the
+* License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Affero General Public License for more details.
+*
+* You should have received a copy of the GNU Affero General Public License
+* along with this program. If not, see .
+*/
+
+mod add;
+pub use add::add_sitekey;
diff --git a/static-assets/bundle/main.css b/static-assets/bundle/main.css
index 1b826757..f4aa8d31 100644
--- a/static-assets/bundle/main.css
+++ b/static-assets/bundle/main.css
@@ -1 +1,265 @@
-body{background-color:#f0f0f0}.form__logo{width:110px;padding-top:50px;display:block;margin:auto;transform:translateY(-40.9%)}.form__brand,.form__logo{position:relative;top:20%}.form__brand{padding:10px 0;text-align:center;transform:translateY(-90.9%)}.form-container{max-width:40%;min-width:20%;position:absolute;top:50%;left:50%;transform:translate(-50%,-49.9%);box-sizing:border-box;margin:auto;padding:20px 0}.form__box{border:1px solid #000;background-color:#f6f8fa;border-radius:5px;padding:20px 0}.form__in-group{display:block;position:relative;margin:auto;max-width:80%;padding:10px 0;box-sizing:content-box;align-items:center;align-content:center}.form__in-field{display:block;box-sizing:border-box;margin:10px 0;padding:10px 0;width:100%}.form__in-field--warn{border:1px solid red}.form__in-field--success{border:1px solid #2ea44f}.form__pw-recovery{text-decoration:none;color:#0366d6;font-size:.8rem}.form__submit-button{display:block;border:1px solid #87ceeb;background:purple;color:hsla(0,0%,100%,.87);height:40px;border-radius:5px;width:80%;margin:auto}.form__secondary-action{display:block;margin-top:10px}.form__secondary-action__banner{display:block;margin:auto;max-width:80%;text-align:center}.form__secondary-action__link{text-decoration:none;color:#0366d6}a{color:inherit}*{margin:0;padding:0}a{text-decoration:none}li{list-style:none}.secondary-menu{position:fixed;width:14%;left:0;bottom:0;top:0;right:0;height:100%;overflow:auto;background-color:#2b2c30;color:hsla(0,0%,100%,.87)}.secondary-menu__heading{margin:auto;padding:20px 5px;display:flex}.secondary-menu__heading:hover{color:#5cad66;cursor:grab}.secondary-menu__logo{width:70px;display:inline-block}.secondary-menu__brand-name{display:inline-block;margin:auto;font-size:1.5rem}.secondary-menu__item{margin:auto;padding:20px 25px;display:flex}.secondary-menu__icon{filter:invert(100%) sepia(0) saturate(0) hue-rotate(93deg) brightness(103%) contrast(103%);opacity:.8;width:1rem;margin:auto 10px auto auto}.secondary-menu__item-name{display:inline-block;margin:auto;font-size:1rem}.secondary-menu__item-link:hover{color:#5cad66;cursor:grab;filter:invert(58%) sepia(60%) saturate(331%) hue-rotate(76deg) brightness(91%) contrast(92%)}.secondary-menu__item-link{color:inherit;width:100%;height:100%}main{position:fixed;top:0;right:0;left:14%;bottom:0;background-color:#f0f0f0}.task-bar{display:flex;padding:0;margin:0;background-color:#fff}.task-bar__action{display:inline-block;padding:10px 0;margin:auto}.task-bar__spacer{min-width:250px;flex:6}.task-bar__icon{opacity:.8;width:1.5rem;margin:auto 20px;color:hsla(0,0%,100%,.87)}.task-bar__icon:hover{cursor:grab}.main-menu{display:flex;flex-grow:0;padding-top:20px;padding-left:10px}.main-menu__item{list-style:none;background-color:#c3c3c3;flex:2;text-align:center;vertical-align:middle;margin:auto 20px;padding:10px 0}.main-menu__item--spacer{list-style:none;flex:3;text-align:center}.main-menu__item:hover{background-color:grey;cursor:grab}.main-menu__item:last-child{padding:0;display:flex;flex:2;border:none;background-color:unset}.main-menu__item:last-child:hover{cursor:unset;background-color:unset}.main-menu__add-site{display:inline-block;background-color:purple;color:#fff;font-weight:500;font-size:16px;padding:10px 15px;border-radius:5px;border:1px solid grey;min-height:45px;margin:auto}.main-menu__add-site:hover{background-color:purple;cursor:grab;transform:translateY(-5px)}.help-text{border-radius:4px;box-shadow:0 2px 6px 0 #2b2c30;min-width:70%;max-width:80%;min-height:70px;display:flex;margin-left:15px;margin-top:40px}.help-text__serial-num{display:inline-flex;background-color:purple;color:hsla(0,0%,100%,.87);width:30px;height:30px;border-radius:50%;align-items:center;justify-content:center}.help-text__instructions{display:inline-block;list-style:none;font-size:19px;font-weight:500;padding:10px;margin:auto}.inner-container{box-sizing:border-box;max-width:50%;margin:50px auto;border-radius:5px;display:flex}.sitekey-form{display:flex;flex-direction:column;width:90%;justify-content:center;align-items:center;box-sizing:content-box;background-color:#fff;margin:auto;padding-bottom:30px}.sitekey-form__title-flex-container{display:flex;width:100%;border-bottom:.1px solid rgba(0,0,0,.125)}.sitekey-form__title{font-size:1rem;padding:.75rem 1.25rem}.sitekey-form__label{display:block;margin:10px 0;box-sizing:inherit;justify-self:left}.sitekey-form__input{position:relative;margin-top:5px;box-sizing:border-box;height:40px;width:90%}.sitekey-form__input--add-level{position:relative;margin-top:5px;box-sizing:inherit;flex:3;height:40px;margin-right:20px}.sitekey-form__add-level-flex-container{display:flex;box-sizing:border-box;width:90%;margin-top:10px}.sitekey-form__add-level-spacer{flex:3}.sitekey-form__add-level{font-size:16px;height:40px;min-width:125px;margin:auto}.sitekey-form__add-level,.sitekey-form__submit{background-color:purple;color:#fff;padding:5px;border-radius:5px;border:1px solid rgba(0,0,0,.125)}.sitekey-form__submit{margin-top:50px;display:block;font-size:20px;min-height:45px;width:125px;width:90%}
\ No newline at end of file
+* {
+ margin: 0;
+ padding: 0; }
+
+a {
+ text-decoration: none; }
+
+li {
+ list-style: none; }
+
+html {
+ height: 100%; }
+
+body {
+ height: 100%; }
+
+.secondary-menu {
+ position: fixed;
+ width: 14%;
+ left: 0;
+ bottom: 0;
+ top: 0;
+ right: 0;
+ height: 100%;
+ overflow: auto;
+ background-color: #2b2c30;
+ color: rgba(255, 255, 255, 0.87); }
+
+.secondary-menu__heading {
+ margin: auto;
+ padding: 20px 5px;
+ display: flex; }
+
+.secondary-menu__heading:hover {
+ color: #5cad66;
+ cursor: grab; }
+
+.secondary-menu__logo {
+ width: 70px;
+ display: inline-block; }
+
+.secondary-menu__brand-name {
+ display: inline-block;
+ margin: auto;
+ font-size: 1.5rem; }
+
+.secondary-menu__item {
+ margin: auto;
+ padding: 20px 25px;
+ display: flex; }
+
+.secondary-menu__icon {
+ filter: invert(100%) sepia(0%) saturate(0%) hue-rotate(93deg) brightness(103%) contrast(103%);
+ opacity: 0.8;
+ width: 1rem;
+ margin: auto;
+ margin-right: 10px; }
+
+.secondary-menu__item-name {
+ display: inline-block;
+ margin: auto;
+ font-size: 1rem; }
+
+.secondary-menu__item-link:hover {
+ color: #5cad66;
+ cursor: grab;
+ filter: invert(58%) sepia(60%) saturate(331%) hue-rotate(76deg) brightness(91%) contrast(92%); }
+
+.secondary-menu__item-link {
+ color: inherit;
+ width: 100%;
+ height: 100%; }
+
+main {
+ margin-left: 14%;
+ min-height: 100%;
+ background-color: #f0f0f0;
+ padding-bottom: 20px; }
+
+.task-bar {
+ display: flex;
+ padding: 0px;
+ margin: 0px;
+ background-color: #fff; }
+
+.task-bar__action {
+ display: inline-block;
+ padding: 10px 0px;
+ margin: auto; }
+
+.task-bar__spacer {
+ min-width: 250px;
+ flex: 6; }
+
+.task-bar__icon {
+ opacity: 0.8;
+ width: 1.5rem;
+ margin: auto 20px; }
+
+.task-bar__icon {
+ color: rgba(255, 255, 255, 0.87); }
+
+.task-bar__icon:hover {
+ cursor: grab; }
+
+.main-menu {
+ display: flex;
+ flex-grow: 0;
+ padding-top: 20px;
+ padding-left: 10px; }
+
+.main-menu__item {
+ list-style: none;
+ background-color: #c3c3c3;
+ flex: 2;
+ text-align: center;
+ vertical-align: middle;
+ margin: auto 20px;
+ padding: 10px 0; }
+
+.main-menu__item--spacer {
+ list-style: none;
+ flex: 3;
+ text-align: center; }
+
+.main-menu__item:hover {
+ background-color: grey;
+ cursor: grab; }
+
+.main-menu__item:last-child {
+ padding: 0;
+ display: flex;
+ flex: 2;
+ border: none;
+ background-color: unset; }
+
+.main-menu__item:last-child:hover {
+ cursor: unset;
+ background-color: unset; }
+
+.main-menu__add-site {
+ display: inline-block;
+ background-color: #800080;
+ color: white;
+ font-weight: 500;
+ font-size: 16px;
+ padding: 10px 15px;
+ border-radius: 5px;
+ border: 1px grey solid;
+ min-height: 45px;
+ margin: auto; }
+
+.main-menu__add-site:hover {
+ background-color: #800080;
+ cursor: grab;
+ transform: translateY(-5px); }
+
+.help-text {
+ border-radius: 4px;
+ box-shadow: #2b2c30 0px 2px 6px 0px;
+ min-width: 70%;
+ max-width: 80%;
+ min-height: 70px;
+ display: flex;
+ margin-left: 15px;
+ margin-top: 40px; }
+
+.help-text__serial-num {
+ display: inline-flex;
+ background-color: #800080;
+ color: rgba(255, 255, 255, 0.87);
+ width: 30px;
+ height: 30px;
+ border-radius: 50%;
+ align-items: center;
+ justify-content: center; }
+
+.help-text__instructions {
+ display: inline-block;
+ list-style: none;
+ font-size: 19px;
+ font-weight: 500;
+ padding: 10px;
+ margin: auto; }
+
+.inner-container {
+ display: flex;
+ box-sizing: border-box;
+ max-width: 50%;
+ margin: 50px auto;
+ border-radius: 5px;
+ display: flex; }
+
+.sitekey-form {
+ display: flex;
+ flex-direction: column;
+ width: 90%;
+ justify-content: center;
+ align-items: center;
+ box-sizing: content-box;
+ background-color: #fff;
+ margin: auto;
+ padding-bottom: 30px; }
+
+.sitekey-form__title-flex-container {
+ display: flex;
+ width: 100%;
+ border-bottom: 0.1px solid rgba(0, 0, 0, 0.125); }
+
+.sitekey-form__title {
+ padding-left: 10px;
+ font-size: 1rem;
+ padding: 0.75rem 1.25rem; }
+
+.sitekey-form__label {
+ display: block;
+ margin: 10px 0;
+ box-sizing: inherit;
+ justify-self: left; }
+
+.sitekey-form__input {
+ position: relative;
+ margin-top: 5px;
+ box-sizing: border-box;
+ height: 40px;
+ width: 90%; }
+
+.sitekey-form__input--add-level {
+ position: relative;
+ margin-top: 5px;
+ box-sizing: inherit;
+ flex: 3;
+ height: 40px;
+ margin-right: 20px; }
+
+.sitekey-form__add-level-flex-container {
+ display: flex;
+ box-sizing: border-box;
+ width: 90%;
+ margin-top: 10px; }
+
+.sitekey-form__add-level-button {
+ background-color: #800080;
+ color: white;
+ padding: 5px;
+ font-size: 16px;
+ border-radius: 5px;
+ border: 1px rgba(0, 0, 0, 0.125) solid;
+ height: 40px;
+ min-width: 125px;
+ margin: auto; }
+
+.sitekey-form__submit {
+ margin-top: 50px;
+ display: block;
+ background-color: #800080;
+ color: white;
+ padding: 5px;
+ font-size: 20px;
+ border-radius: 5px;
+ border: 1px rgba(0, 0, 0, 0.125) solid;
+ min-height: 45px;
+ width: 125px;
+ width: 90%; }
+
diff --git a/static-assets/bundle/main.js b/static-assets/bundle/main.js
index 50ddd2c2..0e31cbd4 100644
--- a/static-assets/bundle/main.js
+++ b/static-assets/bundle/main.js
@@ -1 +1,256 @@
-!function(e){var t={};function n(a){if(t[a])return t[a].exports;var r=t[a]={i:a,l:!1,exports:{}};return e[a].call(r.exports,r,r.exports,n),r.l=!0,r.exports}n.m=e,n.c=t,n.d=function(e,t,a){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:a})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var a=Object.create(null);if(n.r(a),Object.defineProperty(a,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(a,r,function(t){return e[t]}.bind(null,r));return a},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=2)}([function(e,t,n){},function(e,t,n){},function(e,t,n){"use strict";n.r(t);const a=e=>{if(!e)throw new Error("uri is empty");if("string"!=typeof e)throw new TypeError("URI must be a string");let t=e.length;return"/"==e[t-1]&&(e=e.slice(0,t-1)),e};var r={registerUser:"/api/v1/signup",loginUser:"/api/v1/signin",signoutUser:"/api/v1/signout",deleteAccount:"/api/v1/account/delete",usernameExists:"/api/v1/account/username/exists",emailExists:"/api/v1/account/email/exists",healthCheck:"/api/v1/meta/health",buildDetails:"/api/v1/meta/build",addDomain:"/api/v1/mcaptcha/domain/add",challengeDomain:"/api/v1/mcaptcha/domain/domain/verify/challenge/get",proveDomain:"/api/v1/mcaptcha/domain/domain/verify/challenge/prove",deleteDomain:"/api/v1/mcaptcha/domain/delete",addToken:"/api/v1/mcaptcha/domain/token/add",updateTokenKey:"/api/v1/mcaptcha/domain/token/update",getTokenKey:"/api/v1/mcaptcha/domain/token/get",deleteToken:"/api/v1/mcaptcha/domain/token/delete",addTokenLevels:"/api/v1/mcaptcha/domain/token/levels/add",updateTokenLevels:"/api/v1/mcaptcha/domain/token/levels/update",deleteTokenLevels:"/api/v1/mcaptcha/domain/token/levels/delete",getTokenLevels:"/api/v1/mcaptcha/domain/token/levels/get",getTokenDuration:"/api/v1/mcaptcha/domain/token/token/get",updateTokenDuration:"/api/v1/mcaptcha/domain/token/token/update"};var o={registerUser:"/join/",loginUser:"/login/",signoutUser:"/api/v1/signout",panelHome:"/",docsHome:"/docs/"};var i=e=>({method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)});const s=e=>{e.preventDefault();let t=document.getElementById("username").value;i(e,t,"username");let n=document.getElementById("password").value;fetch(r.loginUser,i({username:t,password:n})).then(e=>{e.ok?(alert("success"),window.location.assign(o.panelHome)):e.json().then(e=>alert("error: "+e.error))})};var l=async function(){let e=document.getElementById("username"),t={val:e.value},n=await fetch(r.usernameExists,i(t));if(n.ok){let t=await n.json();return t.exists&&(e.className+=" form__in-field--warn",alert("Username taken")),t.exists}{let e=await n.json();alert("error: "+e.error)}return!1};const u=async e=>{e.preventDefault();let t=document.getElementById("username").value;i(e,t,"username");let n=document.getElementById("password").value;if(n!=document.getElementById("password-check").value)return alert("passwords don't match, check again!");let a=await l();if(a)return;let s=document.getElementById("email").value;if(s.replace(/\s/g,"").length){if(a=await(async()=>{let e=document.getElementById("email"),t={val:e.value},n=await fetch(r.emailExists,i(t));if(n.ok){let t=await n.json();return t.exists&&(e.className+=" form__in-field--warn",alert("Email taken")),t.exists}{let e=await n.json();alert("error: "+e.error)}})(),a)return}else s=null;let u={username:t,password:n,email:s},c=await fetch(r.registerUser,i(u));if(c.ok)alert("success"),window.location.assign(o.loginUser);else{let e=await c.json();alert("error: "+e.error)}};n(0),n(1);const c=new class{constructor(){this.routes=[]}register(e,t){if(!e)throw new Error("uri is empty");if(!t)throw new Error("fn is empty");if("string"!=typeof e)throw new TypeError("URI must be a string");if("function"!=typeof t)throw new TypeError("a callback fn must be provided");this.routes.forEach(t=>{if(t.uri==e)throw new Error(`URI exists. provided URI: ${e}, registered config: ${t}`)});const n={uri:e=a(e),fn:t};this.routes.push(n)}route(){this.routes.forEach(e=>{let t=new RegExp(`^${e.uri}$`),n=window.location.pathname;if(n=a(n),n.match(t))return e.fn.call()})}};c.register(o.panelHome,()=>{}),c.register(o.registerUser,()=>{document.getElementById("form").addEventListener("submit",u,!0),document.getElementById("username").addEventListener("input",l,!1)}),c.register(o.loginUser,()=>{document.getElementById("form").addEventListener("submit",s,!0)}),c.route()}]);
\ No newline at end of file
+/******/ (function(modules) { // webpackBootstrap
+/******/ // The module cache
+/******/ var installedModules = {};
+/******/
+/******/ // The require function
+/******/ function __webpack_require__(moduleId) {
+/******/
+/******/ // Check if module is in cache
+/******/ if(installedModules[moduleId]) {
+/******/ return installedModules[moduleId].exports;
+/******/ }
+/******/ // Create a new module (and put it into the cache)
+/******/ var module = installedModules[moduleId] = {
+/******/ i: moduleId,
+/******/ l: false,
+/******/ exports: {}
+/******/ };
+/******/
+/******/ // Execute the module function
+/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ // Flag the module as loaded
+/******/ module.l = true;
+/******/
+/******/ // Return the exports of the module
+/******/ return module.exports;
+/******/ }
+/******/
+/******/
+/******/ // expose the modules object (__webpack_modules__)
+/******/ __webpack_require__.m = modules;
+/******/
+/******/ // expose the module cache
+/******/ __webpack_require__.c = installedModules;
+/******/
+/******/ // define getter function for harmony exports
+/******/ __webpack_require__.d = function(exports, name, getter) {
+/******/ if(!__webpack_require__.o(exports, name)) {
+/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
+/******/ }
+/******/ };
+/******/
+/******/ // define __esModule on exports
+/******/ __webpack_require__.r = function(exports) {
+/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
+/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
+/******/ }
+/******/ Object.defineProperty(exports, '__esModule', { value: true });
+/******/ };
+/******/
+/******/ // create a fake namespace object
+/******/ // mode & 1: value is a module id, require it
+/******/ // mode & 2: merge all properties of value into the ns
+/******/ // mode & 4: return value when already ns object
+/******/ // mode & 8|1: behave like require
+/******/ __webpack_require__.t = function(value, mode) {
+/******/ if(mode & 1) value = __webpack_require__(value);
+/******/ if(mode & 8) return value;
+/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
+/******/ var ns = Object.create(null);
+/******/ __webpack_require__.r(ns);
+/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
+/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
+/******/ return ns;
+/******/ };
+/******/
+/******/ // getDefaultExport function for compatibility with non-harmony modules
+/******/ __webpack_require__.n = function(module) {
+/******/ var getter = module && module.__esModule ?
+/******/ function getDefault() { return module['default']; } :
+/******/ function getModuleExports() { return module; };
+/******/ __webpack_require__.d(getter, 'a', getter);
+/******/ return getter;
+/******/ };
+/******/
+/******/ // Object.prototype.hasOwnProperty.call
+/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/
+/******/ // __webpack_public_path__
+/******/ __webpack_require__.p = "";
+/******/
+/******/
+/******/ // Load entry module and return exports
+/******/ return __webpack_require__(__webpack_require__.s = "./templates/index.js");
+/******/ })
+/************************************************************************/
+/******/ ({
+
+/***/ "./templates/api/v1/routes.js":
+/*!************************************!*\
+ !*** ./templates/api/v1/routes.js ***!
+ \************************************/
+/*! exports provided: default */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/*\n * Copyright (C) 2021 Aravinth Manivannan \n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as\n * published by the Free Software Foundation, either version 3 of the\n * License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see .\n */\n\nconst ROUTES = {\n registerUser: '/api/v1/signup',\n\n loginUser: '/api/v1/signin',\n\n signoutUser: '/api/v1/signout',\n\n deleteAccount: '/api/v1/account/delete',\n\n usernameExists: '/api/v1/account/username/exists',\n\n emailExists: '/api/v1/account/email/exists',\n\n healthCheck: '/api/v1/meta/health',\n\n buildDetails: '/api/v1/meta/build',\n\n addDomain: '/api/v1/mcaptcha/domain/add',\n\n challengeDomain: '/api/v1/mcaptcha/domain/domain/verify/challenge/get',\n\n proveDomain: '/api/v1/mcaptcha/domain/domain/verify/challenge/prove',\n\n deleteDomain: '/api/v1/mcaptcha/domain/delete',\n\n addToken: '/api/v1/mcaptcha/domain/token/add',\n\n updateTokenKey: '/api/v1/mcaptcha/domain/token/update',\n\n getTokenKey: '/api/v1/mcaptcha/domain/token/get',\n\n deleteToken: '/api/v1/mcaptcha/domain/token/delete',\n\n addTokenLevels: '/api/v1/mcaptcha/domain/token/levels/add',\n\n updateTokenLevels: '/api/v1/mcaptcha/domain/token/levels/update',\n\n deleteTokenLevels: '/api/v1/mcaptcha/domain/token/levels/delete',\n\n getTokenLevels: '/api/v1/mcaptcha/domain/token/levels/get',\n\n getTokenDuration: '/api/v1/mcaptcha/domain/token/token/get',\n\n updateTokenDuration: '/api/v1/mcaptcha/domain/token/token/update',\n};\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (ROUTES);\n\n\n//# sourceURL=webpack:///./templates/api/v1/routes.js?");
+
+/***/ }),
+
+/***/ "./templates/auth/login/index.js":
+/*!***************************************!*\
+ !*** ./templates/auth/login/index.js ***!
+ \***************************************/
+/*! exports provided: index */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"index\", function() { return index; });\n/* harmony import */ var _api_v1_routes__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../api/v1/routes */ \"./templates/api/v1/routes.js\");\n/* harmony import */ var _views_v1_routes__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../views/v1/routes */ \"./templates/views/v1/routes.js\");\n/* harmony import */ var _utils_genJsonPayload__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../utils/genJsonPayload */ \"./templates/utils/genJsonPayload.js\");\n/*\n * Copyright (C) 2021 Aravinth Manivannan \n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as\n * published by the Free Software Foundation, either version 3 of the\n * License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see .\n */\n\n\n\n\n\n\n\n//import '../forms.scss';\n\nconst login = e => {\n e.preventDefault();\n let username = document.getElementById('username').value;\n Object(_utils_genJsonPayload__WEBPACK_IMPORTED_MODULE_2__[\"default\"])(e, username, 'username');\n\n let password = document.getElementById('password').value;\n let payload = {\n username,\n password,\n };\n\n fetch(_api_v1_routes__WEBPACK_IMPORTED_MODULE_0__[\"default\"].loginUser, Object(_utils_genJsonPayload__WEBPACK_IMPORTED_MODULE_2__[\"default\"])(payload)).then(res => {\n if (res.ok) {\n alert('success');\n window.location.assign(_views_v1_routes__WEBPACK_IMPORTED_MODULE_1__[\"default\"].panelHome);\n } else {\n res.json().then(err => alert(`error: ${err.error}`));\n }\n });\n};\n\nconst index = () => {\n let form = document.getElementById('form');\n form.addEventListener('submit', login, true);\n};\n\n\n//# sourceURL=webpack:///./templates/auth/login/index.js?");
+
+/***/ }),
+
+/***/ "./templates/auth/register/emailExists.js":
+/*!************************************************!*\
+ !*** ./templates/auth/register/emailExists.js ***!
+ \************************************************/
+/*! exports provided: checkEmailExists */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"checkEmailExists\", function() { return checkEmailExists; });\n/* harmony import */ var _api_v1_routes__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../api/v1/routes */ \"./templates/api/v1/routes.js\");\n/* harmony import */ var _utils_genJsonPayload__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../utils/genJsonPayload */ \"./templates/utils/genJsonPayload.js\");\n/*\n * Copyright (C) 2021 Aravinth Manivannan \n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as\n * published by the Free Software Foundation, either version 3 of the\n * License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see .\n */\n\n\n\n\n\nconst checkEmailExists = async () => {\n let email = document.getElementById('email');\n let val = email.value;\n let payload = {\n val,\n };\n\n // return fetch(ROUTES.emailExists, genJsonPayload(payload)).then(res => {\n // if (res.ok) {\n // res.json().then(data => {\n // if (data.exists) {\n // console.log(email.className);\n // email.className += ' form__in-field--warn';\n // alert('Email taken');\n // }\n //\n // return data.exists;\n // });\n // } else {\n // res.json().then(err => alert(`error: ${err.error}`));\n // }\n // });\n //\n\n let res = await fetch(_api_v1_routes__WEBPACK_IMPORTED_MODULE_0__[\"default\"].emailExists, Object(_utils_genJsonPayload__WEBPACK_IMPORTED_MODULE_1__[\"default\"])(payload));\n if (res.ok) {\n let data = await res.json();\n if (data.exists) {\n email.className += ' form__in-field--warn';\n alert('Email taken');\n }\n return data.exists;\n } else {\n let err = await res.json();\n alert(`error: ${err.error}`);\n }\n};\n\n\n\n\n//# sourceURL=webpack:///./templates/auth/register/emailExists.js?");
+
+/***/ }),
+
+/***/ "./templates/auth/register/index.js":
+/*!******************************************!*\
+ !*** ./templates/auth/register/index.js ***!
+ \******************************************/
+/*! exports provided: index */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"index\", function() { return index; });\n/* harmony import */ var _api_v1_routes__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../api/v1/routes */ \"./templates/api/v1/routes.js\");\n/* harmony import */ var _views_v1_routes__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../views/v1/routes */ \"./templates/views/v1/routes.js\");\n/* harmony import */ var _utils_genJsonPayload__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../utils/genJsonPayload */ \"./templates/utils/genJsonPayload.js\");\n/* harmony import */ var _userExists__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./userExists */ \"./templates/auth/register/userExists.js\");\n/* harmony import */ var _emailExists__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./emailExists */ \"./templates/auth/register/emailExists.js\");\n/*\n* Copyright (C) 2021 Aravinth Manivannan \n*\n* This program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Affero General Public License as\n* published by the Free Software Foundation, either version 3 of the\n* License, or (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n* GNU Affero General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. If not, see .\n*/\n\n\n\n\n\n\n\n\n\n\n//import '../forms.scss';\n\nconst registerUser = async e => {\n e.preventDefault();\n\n let username = document.getElementById('username').value;\n Object(_utils_genJsonPayload__WEBPACK_IMPORTED_MODULE_2__[\"default\"])(e, username, 'username');\n\n let password = document.getElementById('password').value;\n let passwordCheck = document.getElementById('password-check').value;\n if (password != passwordCheck) {\n return alert(\"passwords don't match, check again!\");\n }\n\n let exists = await Object(_userExists__WEBPACK_IMPORTED_MODULE_3__[\"default\"])();\n if (exists) {\n return;\n }\n\n let email = document.getElementById('email').value;\n if (!email.replace(/\\s/g, '').length) {\n email = null;\n } else {\n exists = await Object(_emailExists__WEBPACK_IMPORTED_MODULE_4__[\"checkEmailExists\"])();\n if (exists) {\n return;\n }\n }\n\n let payload = {\n username,\n password,\n email,\n };\n\n let res = await fetch(_api_v1_routes__WEBPACK_IMPORTED_MODULE_0__[\"default\"].registerUser, Object(_utils_genJsonPayload__WEBPACK_IMPORTED_MODULE_2__[\"default\"])(payload));\n if (res.ok) {\n alert('success');\n window.location.assign(_views_v1_routes__WEBPACK_IMPORTED_MODULE_1__[\"default\"].loginUser);\n } else {\n let err = await res.json();\n alert(`error: ${err.error}`);\n }\n};\n\nconst index = () => {\n let form = document.getElementById('form');\n form.addEventListener('submit', registerUser, true);\n\n let username = document.getElementById('username');\n username.addEventListener('input', _userExists__WEBPACK_IMPORTED_MODULE_3__[\"default\"], false);\n};\n\n\n//# sourceURL=webpack:///./templates/auth/register/index.js?");
+
+/***/ }),
+
+/***/ "./templates/auth/register/userExists.js":
+/*!***********************************************!*\
+ !*** ./templates/auth/register/userExists.js ***!
+ \***********************************************/
+/*! exports provided: default */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _api_v1_routes__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../api/v1/routes */ \"./templates/api/v1/routes.js\");\n/* harmony import */ var _utils_genJsonPayload__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../utils/genJsonPayload */ \"./templates/utils/genJsonPayload.js\");\n/*\n * Copyright (C) 2021 Aravinth Manivannan \n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as\n * published by the Free Software Foundation, either version 3 of the\n * License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see .\n */\n\n\n\n\n\n//export const checkUsernameExists = async () => {\nasync function userExists() {\n let username = document.getElementById('username');\n let val = username.value;\n let payload = {\n val,\n };\n\n // return fetch(ROUTES.usernameExists, genJsonPayload(payload)).then(res => {\n // if (res.ok) {\n // res.json().then(data => {\n // if (data.exists) {\n // username.className += ' form__in-field--warn';\n // alert('Username taken');\n // }\n // return data.exists;\n // });\n // } else {\n // res.json().then(err => alert(`error: ${err.error}`));\n // }\n // });\n //\n\n let res = await fetch(_api_v1_routes__WEBPACK_IMPORTED_MODULE_0__[\"default\"].usernameExists, Object(_utils_genJsonPayload__WEBPACK_IMPORTED_MODULE_1__[\"default\"])(payload));\n if (res.ok) {\n let data = await res.json();\n if (data.exists) {\n username.className += ' form__in-field--warn';\n alert('Username taken');\n }\n return data.exists;\n } else {\n let err = await res.json();\n alert(`error: ${err.error}`);\n }\n return false;\n}\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (userExists);\n\n\n//# sourceURL=webpack:///./templates/auth/register/userExists.js?");
+
+/***/ }),
+
+/***/ "./templates/index.js":
+/*!****************************!*\
+ !*** ./templates/index.js ***!
+ \****************************/
+/*! no exports provided */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _router__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./router */ \"./templates/router.js\");\n/* harmony import */ var _auth_login__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./auth/login */ \"./templates/auth/login/index.js\");\n/* harmony import */ var _auth_register__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./auth/register */ \"./templates/auth/register/index.js\");\n/* harmony import */ var _panel_index__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./panel/index */ \"./templates/panel/index.js\");\n/* harmony import */ var _panel_add_site_key___WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./panel/add-site-key/ */ \"./templates/panel/add-site-key/index.js\");\n/* harmony import */ var _panel_main_scss__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./panel/main.scss */ \"./templates/panel/main.scss\");\n/* harmony import */ var _panel_main_scss__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(_panel_main_scss__WEBPACK_IMPORTED_MODULE_5__);\n/* harmony import */ var _views_v1_routes__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./views/v1/routes */ \"./templates/views/v1/routes.js\");\n/*\n * Copyright (C) 2021 Aravinth Manivannan \n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as\n * published by the Free Software Foundation, either version 3 of the\n * License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see .\n */\n\n\n\n\n\n\n\n//import './auth/forms.scss';\n\n\n\nconst router = new _router__WEBPACK_IMPORTED_MODULE_0__[\"Router\"]();\n\nrouter.register(_views_v1_routes__WEBPACK_IMPORTED_MODULE_6__[\"default\"].panelHome, _panel_index__WEBPACK_IMPORTED_MODULE_3__[\"index\"]);\nrouter.register(_views_v1_routes__WEBPACK_IMPORTED_MODULE_6__[\"default\"].registerUser, _auth_register__WEBPACK_IMPORTED_MODULE_2__[\"index\"]);\nrouter.register(_views_v1_routes__WEBPACK_IMPORTED_MODULE_6__[\"default\"].loginUser, _auth_login__WEBPACK_IMPORTED_MODULE_1__[\"index\"]);\nrouter.register(_views_v1_routes__WEBPACK_IMPORTED_MODULE_6__[\"default\"].addSiteKey, _panel_add_site_key___WEBPACK_IMPORTED_MODULE_4__[\"index\"]);\n\nrouter.route();\n\n\n//# sourceURL=webpack:///./templates/index.js?");
+
+/***/ }),
+
+/***/ "./templates/panel/add-site-key/addLevelButton.js":
+/*!********************************************************!*\
+ !*** ./templates/panel/add-site-key/addLevelButton.js ***!
+ \********************************************************/
+/*! exports provided: addLevelButtonAddEventListener */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"addLevelButtonAddEventListener\", function() { return addLevelButtonAddEventListener; });\n/*\n * Copyright (C) 2021 Aravinth Manivannan \n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as\n * published by the Free Software Foundation, either version 3 of the\n * License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see .\n */\n\nconst LABEL_CONTAINER_CLASS = 'sitekey-form__add-level-flex-container';\nconst ADD_LEVEL_BUTTON = 'sitekey-form__add-level-button';\nconst LABEL_CLASS = 'sitekey-form__label';\nconst INPUT_ID_WITHOUT_LEVEL = 'level';\nconst LABEL_INNER_TEXT_WITHOUT_LEVEL = 'Level ';\nconst INPUT_CLASS = 'sitekey-form__input--add-level';\nconst ADD_LEVEL_BUTTON_INNER_TEXT = 'Add Level';\n\nconst addLevelButtonEventHandler = e => {\n const PREV_LEVEL_CONTAINER = e.target.parentElement;\n e.target.remove();\n\n let numLevels = 0;\n document.querySelectorAll(`.${LABEL_CLASS}`).forEach(_ => numLevels++);\n numLevels = numLevels.toString();\n\n let labelContainer = document.createElement('div');\n labelContainer.className = LABEL_CONTAINER_CLASS;\n\n let inputID = INPUT_ID_WITHOUT_LEVEL + numLevels;\n let label = document.createElement('label');\n label.className = LABEL_CLASS;\n label.htmlFor = inputID;\n label.innerText = LABEL_INNER_TEXT_WITHOUT_LEVEL + numLevels;\n\n labelContainer.appendChild(label);\n\n PREV_LEVEL_CONTAINER.insertAdjacentElement('afterend', labelContainer);\n\n let inputContainer = document.createElement('div');\n inputContainer.className = LABEL_CONTAINER_CLASS;\n\n let input = document.createElement('input');\n input.id = inputID;\n input.name = inputID;\n input.type = 'text';\n input.className = INPUT_CLASS;\n\n inputContainer.appendChild(input);\n\n let button = document.createElement('button');\n button.className = ADD_LEVEL_BUTTON;\n button.innerText = ADD_LEVEL_BUTTON_INNER_TEXT;\n\n inputContainer.appendChild(button);\n\n labelContainer.insertAdjacentElement('afterend', inputContainer);\n\n\n addLevelButtonAddEventListener();\n};\n\nconst addLevelButtonAddEventListener = () => {\n let addLevelButton = document.querySelector(`.${ADD_LEVEL_BUTTON}`);\n addLevelButton.addEventListener('click', addLevelButtonEventHandler);\n};\n\n/*\n
\n\n
\n\n
\n\n\n
\n*/\n\n\n//# sourceURL=webpack:///./templates/panel/add-site-key/addLevelButton.js?");
+
+/***/ }),
+
+/***/ "./templates/panel/add-site-key/form.js":
+/*!**********************************************!*\
+ !*** ./templates/panel/add-site-key/form.js ***!
+ \**********************************************/
+/*! exports provided: addSubmitEventListener */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"addSubmitEventListener\", function() { return addSubmitEventListener; });\n/*\n * Copyright (C) 2021 Aravinth Manivannan \n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as\n * published by the Free Software Foundation, either version 3 of the\n * License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see .\n */\n\nconst SITE_KEY_FORM_CLASS = 'sitekey-form';\nconst FORM = document.querySelector(`.${SITE_KEY_FORM_CLASS}`);\n\nconst addSubmitEventListener = () => {\n FORM.addEventListener('submit', submit, true);\n};\n\nconst submit = async () => {\n alert('submited');\n // get values\n // check validate levels\n // submit\n // handle erros\n}\n\n\n//# sourceURL=webpack:///./templates/panel/add-site-key/form.js?");
+
+/***/ }),
+
+/***/ "./templates/panel/add-site-key/index.js":
+/*!***********************************************!*\
+ !*** ./templates/panel/add-site-key/index.js ***!
+ \***********************************************/
+/*! exports provided: index */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"index\", function() { return index; });\n/* harmony import */ var _addLevelButton__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./addLevelButton */ \"./templates/panel/add-site-key/addLevelButton.js\");\n/* harmony import */ var _form__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./form */ \"./templates/panel/add-site-key/form.js\");\n/*\n * Copyright (C) 2021 Aravinth Manivannan \n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as\n * published by the Free Software Foundation, either version 3 of the\n * License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see .\n */\n\n\n\n\nconst index = () => {\n _addLevelButton__WEBPACK_IMPORTED_MODULE_0__[\"addLevelButtonAddEventListener\"]();\n _form__WEBPACK_IMPORTED_MODULE_1__[\"addSubmitEventListener\"]();\n};\n\n\n//# sourceURL=webpack:///./templates/panel/add-site-key/index.js?");
+
+/***/ }),
+
+/***/ "./templates/panel/index.js":
+/*!**********************************!*\
+ !*** ./templates/panel/index.js ***!
+ \**********************************/
+/*! exports provided: index */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"index\", function() { return index; });\n/*\n * Copyright (C) 2021 Aravinth Manivannan \n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as\n * published by the Free Software Foundation, either version 3 of the\n * License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see .\n */\n\nconst index = () => {\n // const html = document.documentElement;\n // const body = document.body;\n // const menuLinks = document.querySelectorAll('.admin-menu a');\n // const collapseBtn = document.querySelector('.admin-menu .collapse-btn');\n // const toggleMobileMenu = document.querySelector('.toggle-mob-menu');\n // const switchInput = document.querySelector('.switch input');\n // const switchLabel = document.querySelector('.switch label');\n // const switchLabelText = switchLabel.querySelector('span:last-child');\n // const collapsedClass = 'collapsed';\n // const lightModeClass = 'light-mode';\n //\n // /*TOGGLE HEADER STATE*/\n // collapseBtn.addEventListener('click', function() {\n // body.classList.toggle(collapsedClass);\n // this.getAttribute('aria-expanded') == 'true'\n // ? this.setAttribute('aria-expanded', 'false')\n // : this.setAttribute('aria-expanded', 'true');\n // this.getAttribute('aria-label') == 'collapse menu'\n // ? this.setAttribute('aria-label', 'expand menu')\n // : this.setAttribute('aria-label', 'collapse menu');\n // });\n //\n // /*TOGGLE MOBILE MENU*/\n // toggleMobileMenu.addEventListener('click', function() {\n // body.classList.toggle('mob-menu-opened');\n // this.getAttribute('aria-expanded') == 'true'\n // ? this.setAttribute('aria-expanded', 'false')\n // : this.setAttribute('aria-expanded', 'true');\n // this.getAttribute('aria-label') == 'open menu'\n // ? this.setAttribute('aria-label', 'close menu')\n // : this.setAttribute('aria-label', 'open menu');\n // });\n //\n // /*SHOW TOOLTIP ON MENU LINK HOVER*/\n // for (const link of menuLinks) {\n // link.addEventListener('mouseenter', function() {\n // if (\n // body.classList.contains(collapsedClass) &&\n // window.matchMedia('(min-width: 768px)').matches\n // ) {\n // const tooltip = this.querySelector('span').textContent;\n // this.setAttribute('title', tooltip);\n // } else {\n // this.removeAttribute('title');\n // }\n // });\n // }\n //\n // /*TOGGLE LIGHT/DARK MODE*/\n // if (localStorage.getItem('dark-mode') === 'false') {\n // html.classList.add(lightModeClass);\n // switchInput.checked = false;\n // switchLabelText.textContent = 'Light';\n // }\n //\n // switchInput.addEventListener('input', function() {\n // html.classList.toggle(lightModeClass);\n // if (html.classList.contains(lightModeClass)) {\n // switchLabelText.textContent = 'Light';\n // localStorage.setItem('dark-mode', 'false');\n // } else {\n // switchLabelText.textContent = 'Dark';\n // localStorage.setItem('dark-mode', 'true');\n // }\n // });\n //\n let a;\n};\n\n\n//# sourceURL=webpack:///./templates/panel/index.js?");
+
+/***/ }),
+
+/***/ "./templates/panel/main.scss":
+/*!***********************************!*\
+ !*** ./templates/panel/main.scss ***!
+ \***********************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+eval("// extracted by mini-css-extract-plugin\n\n//# sourceURL=webpack:///./templates/panel/main.scss?");
+
+/***/ }),
+
+/***/ "./templates/router.js":
+/*!*****************************!*\
+ !*** ./templates/router.js ***!
+ \*****************************/
+/*! exports provided: Router */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Router\", function() { return Router; });\n/*\n * Copyright (C) 2021 Aravinth Manivannan \n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as\n * published by the Free Software Foundation, either version 3 of the\n * License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see .\n */\n\nconst normalizeUri = uri => {\n if (!uri) {\n throw new Error('uri is empty');\n }\n\n if (typeof uri !== 'string') {\n throw new TypeError('URI must be a string');\n }\n\n let uriLength = uri.length;\n if (uri[uriLength - 1] == '/') {\n uri = uri.slice(0, uriLength - 1);\n }\n return uri;\n};\n\nclass Router {\n constructor() {\n this.routes = [];\n }\n\n register(uri, fn) {\n // typechecks\n if (!uri) {\n throw new Error('uri is empty');\n }\n\n if (!fn) {\n throw new Error('fn is empty');\n }\n if (typeof uri !== 'string') {\n throw new TypeError('URI must be a string');\n }\n\n if (typeof fn !== 'function') {\n throw new TypeError('a callback fn must be provided');\n }\n\n this.routes.forEach(route => {\n if (route.uri == uri) {\n throw new Error(\n `URI exists. provided URI: ${uri}, registered config: ${route}`,\n );\n }\n });\n\n uri = normalizeUri(uri);\n\n const route = {\n uri,\n fn,\n };\n this.routes.push(route);\n }\n\n route() {\n this.routes.forEach(route => {\n // normalize for trailing slash\n let pattern = new RegExp(`^${route.uri}$`);\n let path = window.location.pathname;\n path = normalizeUri(path);\n if (path.match(pattern)) {\n return route.fn.call();\n }\n });\n }\n}\n\n\n//# sourceURL=webpack:///./templates/router.js?");
+
+/***/ }),
+
+/***/ "./templates/utils/genJsonPayload.js":
+/*!*******************************************!*\
+ !*** ./templates/utils/genJsonPayload.js ***!
+ \*******************************************/
+/*! exports provided: default */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/*\n * Copyright (C) 2021 Aravinth Manivannan \n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as\n * published by the Free Software Foundation, either version 3 of the\n * License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see .\n */\n\nconst genJsonPayload = payload => {\n let value = {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(payload),\n };\n return value;\n};\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (genJsonPayload);\n\n\n//# sourceURL=webpack:///./templates/utils/genJsonPayload.js?");
+
+/***/ }),
+
+/***/ "./templates/views/v1/routes.js":
+/*!**************************************!*\
+ !*** ./templates/views/v1/routes.js ***!
+ \**************************************/
+/*! exports provided: default */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/*\n * Copyright (C) 2021 Aravinth Manivannan \n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as\n * published by the Free Software Foundation, either version 3 of the\n * License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see .\n */\n\nconst ROUTES = {\n registerUser: '/join/',\n loginUser: '/login/',\n signoutUser: '/api/v1/signout',\n panelHome: '/',\n docsHome: '/docs/',\n sitekey: '/sitekey',\n addSiteKey: '/sitekey/add',\n};\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (ROUTES);\n\n\n//# sourceURL=webpack:///./templates/views/v1/routes.js?");
+
+/***/ })
+
+/******/ });
\ No newline at end of file
diff --git a/templates/_reset.scss b/templates/_reset.scss
index 448b8018..d1fb7149 100644
--- a/templates/_reset.scss
+++ b/templates/_reset.scss
@@ -1,9 +1,20 @@
* {
- padding: 0;
margin: 0;
+ padding: 0;
}
a {
- text-decoration: none;
- color: inherit;
+ text-decoration: none;
+}
+
+li {
+ list-style: none;
+}
+
+html {
+ height: 100%;
+}
+
+body {
+ height: 100%;
}
diff --git a/templates/api/v1/routes.js b/templates/api/v1/routes.js
index d6bc8355..4e8820cc 100644
--- a/templates/api/v1/routes.js
+++ b/templates/api/v1/routes.js
@@ -1,3 +1,20 @@
+/*
+ * Copyright (C) 2021 Aravinth Manivannan
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
const ROUTES = {
registerUser: '/api/v1/signup',
diff --git a/templates/auth/login/index.js b/templates/auth/login/index.js
index dcf9b2e7..950f6f3a 100644
--- a/templates/auth/login/index.js
+++ b/templates/auth/login/index.js
@@ -1,3 +1,20 @@
+/*
+ * Copyright (C) 2021 Aravinth Manivannan
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
import ROUTES from '../../api/v1/routes';
import VIEWS from '../../views/v1/routes';
diff --git a/templates/auth/register/emailExists.js b/templates/auth/register/emailExists.js
index f1b079c2..92d1970e 100644
--- a/templates/auth/register/emailExists.js
+++ b/templates/auth/register/emailExists.js
@@ -1,3 +1,20 @@
+/*
+ * Copyright (C) 2021 Aravinth Manivannan
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
import ROUTES from '../../api/v1/routes';
import genJsonPayload from '../../utils/genJsonPayload';
diff --git a/templates/auth/register/index.js b/templates/auth/register/index.js
index 1253f72d..753fe46c 100644
--- a/templates/auth/register/index.js
+++ b/templates/auth/register/index.js
@@ -1,3 +1,20 @@
+/*
+* Copyright (C) 2021 Aravinth Manivannan
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Affero General Public License as
+* published by the Free Software Foundation, either version 3 of the
+* License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Affero General Public License for more details.
+*
+* You should have received a copy of the GNU Affero General Public License
+* along with this program. If not, see .
+*/
+
import ROUTES from '../../api/v1/routes';
import VIEWS from '../../views/v1/routes';
diff --git a/templates/auth/register/userExists.js b/templates/auth/register/userExists.js
index ba2277dd..d48dc333 100644
--- a/templates/auth/register/userExists.js
+++ b/templates/auth/register/userExists.js
@@ -1,10 +1,26 @@
+/*
+ * Copyright (C) 2021 Aravinth Manivannan
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
import ROUTES from '../../api/v1/routes';
import genJsonPayload from '../../utils/genJsonPayload';
-
//export const checkUsernameExists = async () => {
-async function userExists() {
+async function userExists() {
let username = document.getElementById('username');
let val = username.value;
let payload = {
@@ -39,6 +55,6 @@ async function userExists() {
alert(`error: ${err.error}`);
}
return false;
-};
+}
export default userExists;
diff --git a/templates/components/headers.html b/templates/components/headers.html
index de90f5fa..fba52e50 100644
--- a/templates/components/headers.html
+++ b/templates/components/headers.html
@@ -3,6 +3,6 @@
- <.= title .>|<.= name .>
+ <.= title .> | <.= name .>
diff --git a/templates/index.js b/templates/index.js
index 6f1c90a3..c8f87889 100644
--- a/templates/index.js
+++ b/templates/index.js
@@ -1,18 +1,35 @@
+/*
+ * Copyright (C) 2021 Aravinth Manivannan
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
import {Router} from './router';
import * as login from './auth/login';
import * as register from './auth/register';
import * as panel from './panel/index';
-import './auth/forms.scss';
+import * as addSiteKey from './panel/add-site-key/';
+//import './auth/forms.scss';
import './panel/main.scss';
import VIEWS from './views/v1/routes';
-
const router = new Router();
router.register(VIEWS.panelHome, panel.index);
router.register(VIEWS.registerUser, register.index);
router.register(VIEWS.loginUser, login.index);
-//router.register('/panel/layout.html/', panel.index);
+router.register(VIEWS.addSiteKey, addSiteKey.index);
router.route();
diff --git a/templates/panel/add-site-key/add-level.html b/templates/panel/add-site-key/add-level.html
new file mode 100644
index 00000000..9659a812
--- /dev/null
+++ b/templates/panel/add-site-key/add-level.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
diff --git a/templates/panel/add-site-key/addLevelButton.js b/templates/panel/add-site-key/addLevelButton.js
new file mode 100644
index 00000000..99076ded
--- /dev/null
+++ b/templates/panel/add-site-key/addLevelButton.js
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2021 Aravinth Manivannan
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+const LABEL_CONTAINER_CLASS = 'sitekey-form__add-level-flex-container';
+const ADD_LEVEL_BUTTON = 'sitekey-form__add-level-button';
+const LABEL_CLASS = 'sitekey-form__label';
+const INPUT_ID_WITHOUT_LEVEL = 'level';
+const LABEL_INNER_TEXT_WITHOUT_LEVEL = 'Level ';
+const INPUT_CLASS = 'sitekey-form__input--add-level';
+const ADD_LEVEL_BUTTON_INNER_TEXT = 'Add Level';
+
+const addLevelButtonEventHandler = e => {
+ const PREV_LEVEL_CONTAINER = e.target.parentElement;
+ e.target.remove();
+
+ let numLevels = 0;
+ document.querySelectorAll(`.${LABEL_CLASS}`).forEach(_ => numLevels++);
+ numLevels = numLevels.toString();
+
+ let labelContainer = document.createElement('div');
+ labelContainer.className = LABEL_CONTAINER_CLASS;
+
+ let inputID = INPUT_ID_WITHOUT_LEVEL + numLevels;
+ let label = document.createElement('label');
+ label.className = LABEL_CLASS;
+ label.htmlFor = inputID;
+ label.innerText = LABEL_INNER_TEXT_WITHOUT_LEVEL + numLevels;
+
+ labelContainer.appendChild(label);
+
+ PREV_LEVEL_CONTAINER.insertAdjacentElement('afterend', labelContainer);
+
+ let inputContainer = document.createElement('div');
+ inputContainer.className = LABEL_CONTAINER_CLASS;
+
+ let input = document.createElement('input');
+ input.id = inputID;
+ input.name = inputID;
+ input.type = 'text';
+ input.className = INPUT_CLASS;
+
+ inputContainer.appendChild(input);
+
+ let button = document.createElement('button');
+ button.className = ADD_LEVEL_BUTTON;
+ button.innerText = ADD_LEVEL_BUTTON_INNER_TEXT;
+
+ inputContainer.appendChild(button);
+
+ labelContainer.insertAdjacentElement('afterend', inputContainer);
+
+
+ addLevelButtonAddEventListener();
+};
+
+export const addLevelButtonAddEventListener = () => {
+ let addLevelButton = document.querySelector(`.${ADD_LEVEL_BUTTON}`);
+ addLevelButton.addEventListener('click', addLevelButtonEventHandler);
+};
+
+/*
+
+
+
+
+
+
+
+
+*/
diff --git a/templates/panel/add-site-key/existing-level.html b/templates/panel/add-site-key/existing-level.html
new file mode 100644
index 00000000..535c4510
--- /dev/null
+++ b/templates/panel/add-site-key/existing-level.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+
diff --git a/templates/panel/add-site-key/form.html b/templates/panel/add-site-key/form.html
index e2bb2ecb..ec5139a4 100644
--- a/templates/panel/add-site-key/form.html
+++ b/templates/panel/add-site-key/form.html
@@ -1,48 +1,25 @@
diff --git a/templates/panel/add-site-key/form.js b/templates/panel/add-site-key/form.js
new file mode 100644
index 00000000..b3f2f588
--- /dev/null
+++ b/templates/panel/add-site-key/form.js
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2021 Aravinth Manivannan
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+const SITE_KEY_FORM_CLASS = 'sitekey-form';
+const FORM = document.querySelector(`.${SITE_KEY_FORM_CLASS}`);
+
+export const addSubmitEventListener = () => {
+ FORM.addEventListener('submit', submit, true);
+};
+
+const submit = async () => {
+ alert('submited');
+ // get values
+ // check validate levels
+ // submit
+ // handle erros
+}
diff --git a/templates/panel/add-site-key/index.js b/templates/panel/add-site-key/index.js
new file mode 100644
index 00000000..b4dd3aeb
--- /dev/null
+++ b/templates/panel/add-site-key/index.js
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2021 Aravinth Manivannan
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+import * as addLevelButton from './addLevelButton';
+import * as addLevelForm from './form';
+
+export const index = () => {
+ addLevelButton.addLevelButtonAddEventListener();
+ addLevelForm.addSubmitEventListener();
+};
diff --git a/templates/panel/header/sidebar/index.html b/templates/panel/header/sidebar/index.html
index ee467d31..e2d1ac78 100644
--- a/templates/panel/header/sidebar/index.html
+++ b/templates/panel/header/sidebar/index.html
@@ -65,7 +65,7 @@