static dir renamed and cookie auth middleware
1
Cargo.lock
generated
|
@ -1296,6 +1296,7 @@ dependencies = [
|
|||
"actix-http",
|
||||
"actix-identity",
|
||||
"actix-rt",
|
||||
"actix-service",
|
||||
"actix-web",
|
||||
"argon2-creds",
|
||||
"cache-buster",
|
||||
|
|
|
@ -28,6 +28,7 @@ actix-identity = "0.3"
|
|||
actix-http = "2.2"
|
||||
actix-rt = "1"
|
||||
actix-cors= "0.5.4"
|
||||
actix-service = "1.0.6"
|
||||
|
||||
|
||||
mime_guess = "2.0.3"
|
||||
|
|
4
build.rs
|
@ -47,8 +47,8 @@ fn cache_bust() {
|
|||
];
|
||||
|
||||
let config = BusterBuilder::default()
|
||||
.source("./static")
|
||||
.result("./prod")
|
||||
.source("./static-assets")
|
||||
.result("./static")
|
||||
.mime_types(types)
|
||||
.copy(true)
|
||||
.follow_links(true)
|
||||
|
|
|
@ -252,7 +252,7 @@ pub async fn signout(id: Identity) -> impl Responder {
|
|||
if let Some(_) = id.identity() {
|
||||
id.forget();
|
||||
}
|
||||
HttpResponse::TemporaryRedirect()
|
||||
HttpResponse::Found()
|
||||
.set_header(header::LOCATION, "/login")
|
||||
.body("")
|
||||
}
|
||||
|
|
|
@ -130,7 +130,7 @@ async fn auth_works() {
|
|||
.to_request(),
|
||||
)
|
||||
.await;
|
||||
assert_eq!(signout_resp.status(), StatusCode::TEMPORARY_REDIRECT);
|
||||
assert_eq!(signout_resp.status(), StatusCode::FOUND);
|
||||
}
|
||||
|
||||
#[actix_rt::test]
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"map":{"./static/img/svg/github.svg":"./prod/img/svg/github.FA9EB1C66F548EC2C7598B94BA6A17275E1EA383D42B6C83351A2388C773E621.svg","./static/img/svg/globe.svg":"./prod/img/svg/globe.44C2A069EBD637663E938ECE7B8E4EC2A8BDE049A8A044EC68D9CB69AE8C592E.svg","./static/img/svg/message-square.svg":"./prod/img/svg/message-square.E246A6B2AAEFCE8A62B9BDD2D155D3B4923C3E48325EAEF099D509A2D7BB4DD1.svg","./static/img/svg/shield.svg":"./prod/img/svg/shield.13AFE15DCB4882B4A940CFDC3E2088A733CD4E6F97F25B211D87C7C9D6DBA2B6.svg","./static/img/svg/filter.svg":"./prod/img/svg/filter.6D5FBD96BA2E2020663AAC4994A991295917D73F3592C07EE103647B655A2275.svg","./static/img/svg/moon.svg":"./prod/img/svg/moon.1E151D68949CA3B2DC7DE34BC25B7586E4175AC3BA7F56DDBB34227334EF7155.svg","./static/img/svg/toggle-left.svg":"./prod/img/svg/toggle-left.E421950C5922E84015F0A86F272AE5637A2ED96E267D2C962543F5994E5D1172.svg","./static/img/svg/menu.svg":"./prod/img/svg/menu.A2C4DD00686F5D23F78885AC4CE3E075FCA78DFBDEA70407667FBBD9801B7A75.svg","./static/img/icon.png":"./prod/img/icon.CC75A040D5F432E5DC9043D10B94BF1FC3BAE1D02A8C2030F655E642EAD4A32C.png","./static/img/svg/key.svg":"./prod/img/svg/key.F0AACBED8D0F7A279977392F92F4DA73C35E905AC73B3C83320D54856E627EEC.svg","./static/img/svg/help-circle.svg":"./prod/img/svg/help-circle.BE230ABD2E05EB05EF6C5B7D04D35A3A43637EF1E046DEF3D244425609B99F81.svg","./static/img/svg/file.svg":"./prod/img/svg/file.F9E376D9F78FFD918D8D592A8B2D97EAAC14E638B5A7AE3C58DDB075375D8E0E.svg","./static/img/icon-trans.png":"./prod/img/icon-trans.7920418313D84DCDB2491E02E52E4BEF374970C216E85BD721274EE51241ECD4.png","./static/img/svg/shield-off.svg":"./prod/img/svg/shield-off.85394A6AD92D550F8EBA72AAB095E078E7A0E3359DF81174532C8D1AF53B5876.svg","./static/img/svg/eye-off.svg":"./prod/img/svg/eye-off.939360B335D1D35B57C3E2070129D14ABB168E4AC137B5BE4F6F8BD450B712F5.svg","./static/img/svg/credit-card.svg":"./prod/img/svg/credit-card.DF612AFE367A7B31410F2F6CD3C7B515B0F1889C0107EA695D840DFFA492E07D.svg","./static/img/svg/settings.svg":"./prod/img/svg/settings.910C6241743C9C694141971BE8E1C4016A1A5BF203E4E9D676D4CE93BD518F4C.svg","./static/img/svg/user.svg":"./prod/img/svg/user.B164ECD2C4A09DC5189F1F252487E2AC6A33646BEA67AF9C528CDA61FE5E146F.svg","./static/img/svg/toggle-right.svg":"./prod/img/svg/toggle-right.15BF49887941593CE3FE09FA73E3CAF1F4B1E8ABCB42A23D85B4FCBC24FDF5AA.svg","./static/img/svg/eye.svg":"./prod/img/svg/eye.9DE4D24D3C9B055D02B94A8AD65E8C0C644852381FDD131A64448B6DA7859167.svg","./static/img/svg/tag.svg":"./prod/img/svg/tag.E0BC111B8E81BBFC62B6A9E7E4AC162B7085A6543D995B7A0030CB7632901BD4.svg","./static/bundle/main.css":"./prod/bundle/main.C7B0ACE647935B5E61BD692A0EB6AFF167CAB2F80483079378CF7A18D7FF9466.css","./static/img/svg/file-text.svg":"./prod/img/svg/file-text.CF57DF252051E7E81C240D36AF1DB8A9DDAF282F9A5E8C338408FE88A6545A02.svg","./static/bundle/main.js":"./prod/bundle/main.736EA02160A042CFB6310C65CB61D8F2578A457254FBDBD1F00009320D8BF903.js","./static/img/svg/bell.svg":"./prod/img/svg/bell.9DA292704EE9907EFDB870F4510C97336977CA27FBFAAD83CF46F8E22D3828F7.svg","./static/img/svg/home.svg":"./prod/img/svg/home.28C26C2D3E4013D24D755A589A80D8DD5C49DA5397032E3F09B76BC3A2C314ED.svg","./static/img/svg/log-out.svg":"./prod/img/svg/log-out.92AB4384FD41D9AFE4735C480361BB64789CD767B7DD0FF3C6F56287B3D4498E.svg"},"base_dir":"./prod"}
|
||||
{"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"}
|
26
src/main.rs
|
@ -18,10 +18,9 @@ use std::env;
|
|||
|
||||
use actix_identity::{CookieIdentityPolicy, IdentityService};
|
||||
use actix_web::{
|
||||
client::Client, error::InternalError, http::StatusCode, middleware, web::JsonConfig, App,
|
||||
HttpServer,
|
||||
client::Client, error::InternalError, http::StatusCode, middleware as actix_middleware,
|
||||
web::JsonConfig, App, HttpServer,
|
||||
};
|
||||
use cache_buster::Files as FileMap;
|
||||
use lazy_static::lazy_static;
|
||||
use log::info;
|
||||
|
||||
|
@ -35,19 +34,18 @@ mod templates;
|
|||
#[cfg(test)]
|
||||
#[macro_use]
|
||||
mod tests;
|
||||
mod middleware;
|
||||
|
||||
pub use data::Data;
|
||||
pub use settings::Settings;
|
||||
use static_assets::FileMap;
|
||||
|
||||
lazy_static! {
|
||||
pub static ref SETTINGS: Settings = Settings::new().unwrap();
|
||||
pub static ref S: String = env::var("S").unwrap();
|
||||
pub static ref FILES: FileMap = {
|
||||
let map = include_str!("cache_buster_data.json");
|
||||
FileMap::new(&map)
|
||||
};
|
||||
pub static ref JS: &'static str = FILES.get("./static/bundle/main.js").unwrap();
|
||||
pub static ref CSS: &'static str = FILES.get("./static/bundle/main.css").unwrap();
|
||||
pub static ref FILES: FileMap = FileMap::new();
|
||||
pub static ref JS: &'static str = FILES.get("./static-assets/bundle/main.js").unwrap();
|
||||
pub static ref CSS: &'static str = FILES.get("./static-assets/bundle/main.css").unwrap();
|
||||
}
|
||||
|
||||
pub static OPEN_API_DOC: &str = env!("OPEN_API_DOCS");
|
||||
|
@ -77,19 +75,19 @@ async fn main() -> std::io::Result<()> {
|
|||
let client = Client::default();
|
||||
|
||||
App::new()
|
||||
.wrap(middleware::Logger::default())
|
||||
.wrap(actix_middleware::Logger::default())
|
||||
.wrap(get_identity_service())
|
||||
.wrap(middleware::Compress::default())
|
||||
.wrap(actix_middleware::Compress::default())
|
||||
.data(data.clone())
|
||||
.data(client.clone())
|
||||
.wrap(middleware::NormalizePath::new(
|
||||
middleware::normalize::TrailingSlash::Trim,
|
||||
.wrap(actix_middleware::NormalizePath::new(
|
||||
actix_middleware::normalize::TrailingSlash::Trim,
|
||||
))
|
||||
.configure(v1::pow::services)
|
||||
.configure(v1::services)
|
||||
.configure(docs::services)
|
||||
.configure(templates::services)
|
||||
.configure(static_assets::services)
|
||||
.configure(templates::services)
|
||||
.app_data(get_json_err())
|
||||
})
|
||||
.bind(SETTINGS.server.get_ip())
|
||||
|
|
126
src/middleware/auth.rs
Normal file
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* Copyright (C) 2021 Aravinth Manivannan <realaravinth@batsense.net>
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#![allow(clippy::type_complexity)]
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
use actix_identity::Identity;
|
||||
//use actix_identity::{CookieIdentityPolicy, IdentityService};
|
||||
use actix_service::{Service, Transform};
|
||||
use actix_web::dev::{ServiceRequest, ServiceResponse};
|
||||
use actix_web::{http, Error, FromRequest, HttpResponse};
|
||||
|
||||
use futures::future::{ok, Either, Ready};
|
||||
|
||||
pub struct CheckLogin;
|
||||
|
||||
const LOGIN_ROUTE: &str = "/login";
|
||||
|
||||
impl<S, B> Transform<S> for CheckLogin
|
||||
where
|
||||
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
|
||||
S::Future: 'static,
|
||||
{
|
||||
type Request = ServiceRequest;
|
||||
type Response = ServiceResponse<B>;
|
||||
type Error = Error;
|
||||
type Transform = CheckLoginMiddleware<S>;
|
||||
type InitError = ();
|
||||
type Future = Ready<Result<Self::Transform, Self::InitError>>;
|
||||
|
||||
fn new_transform(&self, service: S) -> Self::Future {
|
||||
ok(CheckLoginMiddleware { service })
|
||||
}
|
||||
}
|
||||
//
|
||||
//pub fn auto_login(req: &HttpRequest, pl: &mut dev::Payload) -> Option<()> {
|
||||
// dbg!("login");
|
||||
// if let Some(_) = Identity::from_request(req, pl)
|
||||
// .into_inner()
|
||||
// .map(|x| x.identity())
|
||||
// .unwrap()
|
||||
// {
|
||||
// Some(())
|
||||
// } else {
|
||||
// None
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//fn not_auth(path: &str) -> bool {
|
||||
// let paths = ["/login", "/css", "/img", "/js"];
|
||||
// paths.iter().any(|x| path.starts_with(x))
|
||||
//}
|
||||
|
||||
pub struct CheckLoginMiddleware<S> {
|
||||
service: S,
|
||||
}
|
||||
|
||||
impl<S, B> Service for CheckLoginMiddleware<S>
|
||||
where
|
||||
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
|
||||
S::Future: 'static,
|
||||
{
|
||||
type Request = ServiceRequest;
|
||||
type Response = ServiceResponse<B>;
|
||||
type Error = Error;
|
||||
type Future = Either<S::Future, Ready<Result<Self::Response, Self::Error>>>;
|
||||
|
||||
fn poll_ready(&mut self, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
|
||||
self.service.poll_ready(cx)
|
||||
}
|
||||
|
||||
fn call(&mut self, req: ServiceRequest) -> Self::Future {
|
||||
// if not_auth(req.path()) {
|
||||
// return Either::Left(self.service.call(req));
|
||||
// };
|
||||
let (r, mut pl) = req.into_parts();
|
||||
|
||||
// TODO investigate when the bellow statement will
|
||||
// return error
|
||||
if let Ok(Some(_)) = Identity::from_request(&r, &mut pl)
|
||||
.into_inner()
|
||||
.map(|x| x.identity())
|
||||
{
|
||||
let req = ServiceRequest::from_parts(r, pl).ok().unwrap();
|
||||
Either::Left(self.service.call(req))
|
||||
// Some(())
|
||||
} else {
|
||||
let req = ServiceRequest::from_parts(r, pl).ok().unwrap();
|
||||
Either::Right(ok(req.into_response(
|
||||
HttpResponse::Found()
|
||||
.header(http::header::LOCATION, LOGIN_ROUTE)
|
||||
.finish()
|
||||
.into_body(),
|
||||
)))
|
||||
|
||||
//None
|
||||
}
|
||||
|
||||
// let token = auto_login(&r, &mut pl);
|
||||
// let req = ServiceRequest::from_parts(r, pl).ok().unwrap();
|
||||
// if token.is_some() {
|
||||
// Either::Left(self.service.call(req))
|
||||
// } else {
|
||||
// Either::Right(ok(req.into_response(
|
||||
// HttpResponse::Found()
|
||||
// .header(http::header::LOCATION, LOGIN_ROUTE)
|
||||
// .finish()
|
||||
// .into_body(),
|
||||
// )))
|
||||
// }
|
||||
}
|
||||
}
|
18
src/middleware/mod.rs
Normal file
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* Copyright (C) 2021 Aravinth Manivannan <realaravinth@batsense.net>
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
pub mod auth;
|
|
@ -17,13 +17,14 @@
|
|||
|
||||
use actix_web::body::Body;
|
||||
use actix_web::{get, web, HttpResponse, Responder};
|
||||
use cache_buster::Files;
|
||||
use mime_guess::from_path;
|
||||
use rust_embed::RustEmbed;
|
||||
|
||||
use std::borrow::Cow;
|
||||
|
||||
#[derive(RustEmbed)]
|
||||
#[folder = "prod/"]
|
||||
#[folder = "static/"]
|
||||
struct Asset;
|
||||
|
||||
pub fn handle_embedded_file(path: &str) -> HttpResponse {
|
||||
|
@ -41,7 +42,7 @@ pub fn handle_embedded_file(path: &str) -> HttpResponse {
|
|||
}
|
||||
}
|
||||
|
||||
#[get("/{_:.*}")]
|
||||
#[get("/static/{_:.*}")]
|
||||
async fn dist(path: web::Path<String>) -> impl Responder {
|
||||
handle_embedded_file(&path.0)
|
||||
}
|
||||
|
@ -50,6 +51,29 @@ pub fn services(cfg: &mut web::ServiceConfig) {
|
|||
cfg.service(dist);
|
||||
}
|
||||
|
||||
pub struct FileMap {
|
||||
files: Files,
|
||||
}
|
||||
|
||||
impl FileMap {
|
||||
pub fn new() -> Self {
|
||||
let map = include_str!("cache_buster_data.json");
|
||||
let files = Files::new(&map);
|
||||
Self { files }
|
||||
}
|
||||
pub fn get<'a>(&'a self, path: &'a str) -> Option<&'a str> {
|
||||
// let file_path = self.files.get(path);
|
||||
let file_path = self.files.get_full_path(path);
|
||||
|
||||
if file_path.is_some() {
|
||||
let file_path = &file_path.unwrap()[1..];
|
||||
return Some(file_path);
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use actix_web::http::StatusCode;
|
||||
|
@ -69,4 +93,12 @@ mod tests {
|
|||
.await;
|
||||
assert_eq!(resp.status(), StatusCode::OK);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn filemap_works() {
|
||||
let files = super::FileMap::new();
|
||||
let css = files.get("./static-assets/bundle/main.css").unwrap();
|
||||
println!("{}", css);
|
||||
assert!(css.contains("/static/bundle/main"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,13 +20,13 @@ use actix_web::web::ServiceConfig;
|
|||
mod auth;
|
||||
mod panel;
|
||||
|
||||
pub fn services(cfg: &mut ServiceConfig) {
|
||||
cfg.service(auth::login::login);
|
||||
cfg.service(auth::register::join);
|
||||
pub use crate::middleware::auth::CheckLogin;
|
||||
|
||||
// panel
|
||||
pub fn services(cfg: &mut ServiceConfig) {
|
||||
cfg.service(panel::panel);
|
||||
cfg.service(panel::sitekey::add_sitekey);
|
||||
cfg.service(auth::login::login);
|
||||
cfg.service(auth::register::join);
|
||||
}
|
||||
|
||||
#[cfg(not(tarpaulin_include))]
|
||||
|
@ -39,18 +39,27 @@ mod tests {
|
|||
use crate::*;
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn templates_work() {
|
||||
async fn protected_pages_templates_work() {
|
||||
let mut app = test::init_service(App::new().configure(services)).await;
|
||||
let urls = vec!["/", "/join", "/login", "/sitekey/add"];
|
||||
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;
|
||||
if url == urls.get(0).unwrap() {
|
||||
assert_eq!(resp.status(), StatusCode::TEMPORARY_REDIRECT);
|
||||
} else {
|
||||
assert_eq!(resp.status(), StatusCode::OK);
|
||||
}
|
||||
assert_eq!(resp.status(), StatusCode::FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn public_pages_tempaltes_work() {
|
||||
let mut app = test::init_service(App::new().configure(services)).await;
|
||||
let urls = vec!["/join", "/login"];
|
||||
|
||||
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::OK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ use actix_web::{get, HttpResponse, Responder};
|
|||
use sailfish::TemplateOnce;
|
||||
|
||||
use crate::api::v1::auth::is_authenticated;
|
||||
pub use crate::middleware::auth::CheckLogin;
|
||||
|
||||
pub mod sitekey;
|
||||
|
||||
|
@ -42,7 +43,7 @@ impl<'a> Default for IndexPage<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
#[get("/")]
|
||||
#[get("/", wrap = "CheckLogin")]
|
||||
pub async fn panel(id: Identity) -> impl Responder {
|
||||
if is_authenticated(&id).is_err() {
|
||||
return HttpResponse::TemporaryRedirect()
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
use actix_web::{get, HttpResponse, Responder};
|
||||
use sailfish::TemplateOnce;
|
||||
|
||||
use super::CheckLogin;
|
||||
|
||||
#[derive(TemplateOnce, Clone)]
|
||||
#[template(path = "panel/add-site-key/index.html")]
|
||||
pub struct IndexPage<'a> {
|
||||
|
@ -36,7 +38,7 @@ impl<'a> Default for IndexPage<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
#[get("/sitekey/add")]
|
||||
#[get("/sitekey/add", wrap = "CheckLogin")]
|
||||
pub async fn add_sitekey() -> impl Responder {
|
||||
let body = IndexPage::default().render_once().unwrap();
|
||||
HttpResponse::Ok()
|
||||
|
|
|
@ -1 +1 @@
|
|||
!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)}},c=()=>{};n(0),n(1);const d=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()})}};d.register("/",c),d.register("/register",()=>{document.getElementById("form").addEventListener("submit",u,!0),document.getElementById("username").addEventListener("input",l,!1)}),d.register("/login",()=>{document.getElementById("form").addEventListener("submit",s,!0)}),d.register("/panel/layout.html/",c),d.route()}]);
|
||||
!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()}]);
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.3 MiB |
Before Width: | Height: | Size: 455 KiB After Width: | Height: | Size: 455 KiB |
Before Width: | Height: | Size: 321 B After Width: | Height: | Size: 321 B |
Before Width: | Height: | Size: 329 B After Width: | Height: | Size: 329 B |
Before Width: | Height: | Size: 460 B After Width: | Height: | Size: 460 B |
Before Width: | Height: | Size: 316 B After Width: | Height: | Size: 316 B |
Before Width: | Height: | Size: 473 B After Width: | Height: | Size: 473 B |
Before Width: | Height: | Size: 337 B After Width: | Height: | Size: 337 B |
Before Width: | Height: | Size: 290 B After Width: | Height: | Size: 290 B |
Before Width: | Height: | Size: 528 B After Width: | Height: | Size: 528 B |
Before Width: | Height: | Size: 409 B After Width: | Height: | Size: 409 B |
Before Width: | Height: | Size: 365 B After Width: | Height: | Size: 365 B |
Before Width: | Height: | Size: 332 B After Width: | Height: | Size: 332 B |
Before Width: | Height: | Size: 352 B After Width: | Height: | Size: 352 B |
Before Width: | Height: | Size: 367 B After Width: | Height: | Size: 367 B |
Before Width: | Height: | Size: 346 B After Width: | Height: | Size: 346 B |
Before Width: | Height: | Size: 305 B After Width: | Height: | Size: 305 B |
Before Width: | Height: | Size: 281 B After Width: | Height: | Size: 281 B |
Before Width: | Height: | Size: 1,011 B After Width: | Height: | Size: 1,011 B |
Before Width: | Height: | Size: 405 B After Width: | Height: | Size: 405 B |
Before Width: | Height: | Size: 279 B After Width: | Height: | Size: 279 B |
Before Width: | Height: | Size: 355 B After Width: | Height: | Size: 355 B |
Before Width: | Height: | Size: 323 B After Width: | Height: | Size: 323 B |
Before Width: | Height: | Size: 325 B After Width: | Height: | Size: 325 B |
Before Width: | Height: | Size: 313 B After Width: | Height: | Size: 313 B |
After Width: | Height: | Size: 1.3 MiB |
After Width: | Height: | Size: 455 KiB |
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="52" height="52" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-bell"><path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"></path><path d="M13.73 21a2 2 0 0 1-3.46 0"></path></svg>
|
After Width: | Height: | Size: 321 B |
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="52" height="52" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-credit-card"><rect x="1" y="4" width="22" height="16" rx="2" ry="2"></rect><line x1="1" y1="10" x2="23" y2="10"></line></svg>
|
After Width: | Height: | Size: 329 B |
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="52" height="52" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-eye-off"><path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"></path><line x1="1" y1="1" x2="23" y2="23"></line></svg>
|
After Width: | Height: | Size: 460 B |
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="52" height="52" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-eye"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path><circle cx="12" cy="12" r="3"></circle></svg>
|
After Width: | Height: | Size: 316 B |
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="52" height="52" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path><polyline points="14 2 14 8 20 8"></polyline><line x1="16" y1="13" x2="8" y2="13"></line><line x1="16" y1="17" x2="8" y2="17"></line><polyline points="10 9 9 9 8 9"></polyline></svg>
|
After Width: | Height: | Size: 473 B |
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="52" height="52" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file"><path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path><polyline points="13 2 13 9 20 9"></polyline></svg>
|
After Width: | Height: | Size: 337 B |
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="52" height="52" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-filter"><polygon points="22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3"></polygon></svg>
|
After Width: | Height: | Size: 290 B |
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="52" height="52" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-github"><path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"></path></svg>
|
After Width: | Height: | Size: 528 B |
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="52" height="52" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-globe"><circle cx="12" cy="12" r="10"></circle><line x1="2" y1="12" x2="22" y2="12"></line><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"></path></svg>
|
After Width: | Height: | Size: 409 B |
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="52" height="52" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-help-circle"><circle cx="12" cy="12" r="10"></circle><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"></path><line x1="12" y1="17" x2="12.01" y2="17"></line></svg>
|
After Width: | Height: | Size: 365 B |
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="52" height="52" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-home"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path><polyline points="9 22 9 12 15 12 15 22"></polyline></svg>
|
After Width: | Height: | Size: 332 B |
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-key"><path d="M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.778 7.778 5.5 5.5 0 0 1 7.777-7.777zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3m-3.5 3.5L19 4"></path></svg>
|
After Width: | Height: | Size: 352 B |
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="52" height="52" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-log-out"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"></path><polyline points="16 17 21 12 16 7"></polyline><line x1="21" y1="12" x2="9" y2="12"></line></svg>
|
After Width: | Height: | Size: 367 B |
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="52" height="52" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-menu"><line x1="3" y1="12" x2="21" y2="12"></line><line x1="3" y1="6" x2="21" y2="6"></line><line x1="3" y1="18" x2="21" y2="18"></line></svg>
|
After Width: | Height: | Size: 346 B |
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-message-square"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path></svg>
|
After Width: | Height: | Size: 305 B |
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="52" height="52" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-moon"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path></svg>
|
After Width: | Height: | Size: 281 B |
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="52" height="52" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-settings"><circle cx="12" cy="12" r="3"></circle><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path></svg>
|
After Width: | Height: | Size: 1,011 B |
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="52" height="52" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-shield-off"><path d="M19.69 14a6.9 6.9 0 0 0 .31-2V5l-8-3-3.16 1.18"></path><path d="M4.73 4.73L4 5v7c0 6 8 10 8 10a20.29 20.29 0 0 0 5.62-4.38"></path><line x1="1" y1="1" x2="23" y2="23"></line></svg>
|
After Width: | Height: | Size: 405 B |
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="52" height="52" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-shield"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"></path></svg>
|
After Width: | Height: | Size: 279 B |
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="52" height="52" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-tag"><path d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z"></path><line x1="7" y1="7" x2="7.01" y2="7"></line></svg>
|
After Width: | Height: | Size: 355 B |
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="52" height="52" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-toggle-left"><rect x="1" y="5" width="22" height="14" rx="7" ry="7"></rect><circle cx="8" cy="12" r="3"></circle></svg>
|
After Width: | Height: | Size: 323 B |
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="52" height="52" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-toggle-right"><rect x="1" y="5" width="22" height="14" rx="7" ry="7"></rect><circle cx="16" cy="12" r="3"></circle></svg>
|
After Width: | Height: | Size: 325 B |
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="52" height="52" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-user"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path><circle cx="12" cy="7" r="4"></circle></svg>
|
After Width: | Height: | Size: 313 B |
|
@ -1,9 +1,9 @@
|
|||
<. include!("../../components/headers.html"); .>
|
||||
<div class="form-container">
|
||||
<img src="<.= crate::FILES.get("./static/img/icon-trans.png").unwrap().>" class="form__logo" alt="" />
|
||||
<img src="<.= crate::FILES.get("./static-assets/img/icon-trans.png").unwrap().>" class="form__logo" alt="" />
|
||||
<h2 class="form__brand">Sign in to mCaptcha</h2>
|
||||
|
||||
<form class="form__box" id="form">
|
||||
<form method="POST" class="form__box" id="form">
|
||||
<label class="form__in-group" for="username"
|
||||
>Username
|
||||
<input
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<. include!("../../components/headers.html"); .>
|
||||
<div class="form-container">
|
||||
<img src="<.= crate::FILES.get("./static/img/icon-trans.png").unwrap().>" class="form__logo" alt="" />
|
||||
<img src="<.= crate::FILES.get("./static-assets/img/icon-trans.png").unwrap().>" class="form__logo" alt="" />
|
||||
<h2 class="form__brand">Join mCaptcha</h2>
|
||||
|
||||
<form class="form__box" id="form">
|
||||
<form method="POST" class="form__box" id="form">
|
||||
<label class="form__in-group" for="username"
|
||||
>Username
|
||||
<input
|
||||
|
|
|
@ -5,12 +5,14 @@ import * as register from './auth/register';
|
|||
import * as panel from './panel/index';
|
||||
import './auth/forms.scss';
|
||||
import './panel/main.scss';
|
||||
import VIEWS from './views/v1/routes';
|
||||
|
||||
|
||||
const router = new Router();
|
||||
|
||||
router.register('/', panel.index);
|
||||
router.register('/register', register.index);
|
||||
router.register('/login', login.index);
|
||||
router.register('/panel/layout.html/', panel.index);
|
||||
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.route();
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<nav class="secondary-menu">
|
||||
<ul>
|
||||
<li class="secondary-menu__heading">
|
||||
<img class="secondary-menu__logo" src="<.= crate::FILES.get("./static/img/icon-trans.png").unwrap() .>" alt="Logo" />
|
||||
<img class="secondary-menu__logo" src="<.= crate::FILES.get("./static-assets/img/icon-trans.png").unwrap() .>" alt="Logo" />
|
||||
<div class="secondary-menu__brand-name">
|
||||
mCaptcha
|
||||
</div>
|
||||
|
@ -12,7 +12,7 @@
|
|||
-->
|
||||
<li class="secondary-menu__item">
|
||||
<a class="secondary-menu__item-link" href="/panel">
|
||||
<img class="secondary-menu__icon" src="<.= crate::FILES.get("./static/img/svg/home.svg").unwrap() .>" alt="" />
|
||||
<img class="secondary-menu__icon" src="<.= crate::FILES.get("./static-assets/img/svg/home.svg").unwrap() .>" alt="" />
|
||||
<div class="secondary-menu__item-name">
|
||||
Overview
|
||||
</div>
|
||||
|
@ -20,7 +20,7 @@
|
|||
</li>
|
||||
<li class="secondary-menu__item">
|
||||
<a class="secondary-menu__item-link" href="/panel/sitekey">
|
||||
<img class="secondary-menu__icon" src="<.= crate::FILES.get("./static/img/svg/key.svg").unwrap() .>" alt="" />
|
||||
<img class="secondary-menu__icon" src="<.= crate::FILES.get("./static-assets/img/svg/key.svg").unwrap() .>" alt="" />
|
||||
<div class="secondary-menu__item-name">
|
||||
Site Keys
|
||||
</div>
|
||||
|
@ -29,7 +29,7 @@
|
|||
|
||||
<li class="secondary-menu__item">
|
||||
<a class="secondary-menu__item-link" href="">
|
||||
<img class="secondary-menu__icon" src="<.= crate::FILES.get("./static/img/svg/settings.svg").unwrap() .>" alt="" />
|
||||
<img class="secondary-menu__icon" src="<.= crate::FILES.get("./static-assets/img/svg/settings.svg").unwrap() .>" alt="" />
|
||||
<div class="secondary-menu__item-name">
|
||||
Settings
|
||||
</div>
|
||||
|
@ -37,7 +37,7 @@
|
|||
</li>
|
||||
<li class="secondary-menu__item">
|
||||
<a class="secondary-menu__item-link" href="">
|
||||
<img class="secondary-menu__icon" src="<.= crate::FILES.get("./static/img/svg/credit-card.svg").unwrap() .>" alt="" />
|
||||
<img class="secondary-menu__icon" src="<.= crate::FILES.get("./static-assets/img/svg/credit-card.svg").unwrap() .>" alt="" />
|
||||
<div class="secondary-menu__item-name">
|
||||
Billing
|
||||
</div>
|
||||
|
@ -45,7 +45,7 @@
|
|||
</li>
|
||||
<li class="secondary-menu__item">
|
||||
<a class="secondary-menu__item-link" href="">
|
||||
<img class="secondary-menu__icon" src="<.= crate::FILES.get("./static/img/svg/help-circle.svg").unwrap() .>" alt="" />
|
||||
<img class="secondary-menu__icon" src="<.= crate::FILES.get("./static-assets/img/svg/help-circle.svg").unwrap() .>" alt="" />
|
||||
<div class="secondary-menu__item-name">
|
||||
Help
|
||||
</div>
|
||||
|
@ -55,7 +55,7 @@
|
|||
<a class="secondary-menu__item-link" href="">
|
||||
<img
|
||||
class="secondary-menu__icon"
|
||||
src="<.= crate::FILES.get("./static/img/svg/message-square.svg").unwrap() .>"
|
||||
src="<.= crate::FILES.get("./static-assets/img/svg/message-square.svg").unwrap() .>"
|
||||
alt=""
|
||||
/>
|
||||
|
||||
|
@ -66,7 +66,7 @@
|
|||
</li>
|
||||
<li class="secondary-menu__item">
|
||||
<a class="secondary-menu__item-link" href="">
|
||||
<img class="secondary-menu__icon" src="<.= crate::FILES.get("./static/img/svg/file-text.svg").unwrap() .>" alt="" />
|
||||
<img class="secondary-menu__icon" src="<.= crate::FILES.get("./static-assets/img/svg/file-text.svg").unwrap() .>" alt="" />
|
||||
<div class="secondary-menu__item-name">
|
||||
API Docs
|
||||
</div>
|
||||
|
@ -75,7 +75,7 @@
|
|||
<li class="secondary-menu__item">
|
||||
<a class="secondary-menu__item-link" href="">
|
||||
<img class="secondary-menu__icon"
|
||||
src="<.= crate::FILES.get("./static/img/svg/github.svg").unwrap() .>" alt="" />
|
||||
src="<.= crate::FILES.get("./static-assets/img/svg/github.svg").unwrap() .>" alt="" />
|
||||
<div class="secondary-menu__item-name">
|
||||
Source Code
|
||||
</div>
|
||||
|
|
|
@ -12,19 +12,19 @@
|
|||
</li>
|
||||
<li class="task-bar__action">
|
||||
<img class="task-bar__icon" src="<.=
|
||||
crate::FILES.get("./static/img/svg/moon.svg").unwrap() .>" alt="Profile" />
|
||||
crate::FILES.get("./static-assets/img/svg/moon.svg").unwrap() .>" alt="Profile" />
|
||||
</li>
|
||||
|
||||
<li class="task-bar__action">
|
||||
<img class="task-bar__icon" src="<.=
|
||||
crate::FILES.get("./static/img/svg/bell.svg").unwrap() .>"
|
||||
crate::FILES.get("./static-assets/img/svg/bell.svg").unwrap() .>"
|
||||
alt="Notifications" />
|
||||
</li>
|
||||
|
||||
<li class="task-bar__action">
|
||||
<a href="/logout">
|
||||
<img class="task-bar__icon" src="<.=
|
||||
crate::FILES.get("./static/img/svg/log-out.svg").unwrap() .>" alt="Profile"
|
||||
crate::FILES.get("./static-assets/img/svg/log-out.svg").unwrap() .>" alt="Profile"
|
||||
/></a>
|
||||
</li>
|
||||
</ul>
|
||||
|
|
|
@ -7,7 +7,7 @@ module.exports = merge(common, {
|
|||
mode: 'development',
|
||||
output: {
|
||||
filename: '[name].js',
|
||||
path: path.resolve(__dirname, 'static/bundle'),
|
||||
path: path.resolve(__dirname, 'static-assets/bundle'),
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
|
|
|
@ -11,7 +11,7 @@ module.exports = merge(common, {
|
|||
mode: 'production',
|
||||
output: {
|
||||
filename: '[name].js',
|
||||
path: path.resolve(__dirname, 'static/bundle'),
|
||||
path: path.resolve(__dirname, 'static-assets/bundle'),
|
||||
},
|
||||
optimization: {
|
||||
minimizer: [
|
||||
|
|