diff --git a/.gitignore b/.gitignore index 70e3cae..3b7f426 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ - +/node_modules /target **/*.rs.bk diff --git a/package.json b/package.json new file mode 100644 index 0000000..13dc0dc --- /dev/null +++ b/package.json @@ -0,0 +1,39 @@ +{ + "name": "garbage-pile", + "version": "1.0.0", + "description": "A Verifying OpenPGP Key Server", + "main": "", + "scripts": { + "build": "webpack", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+ssh://git@gitlab.com/sequoia-pgp/garbage-pile.git" + }, + "author": "kai@sequoia-pgp.org", + "license": "GPL-3.0", + "bugs": { + "url": "https://gitlab.com/sequoia-pgp/garbage-pile/issues" + }, + "homepage": "https://gitlab.com/sequoia-pgp/garbage-pile#README", + "dependencies": { + "bootstrap": "^4.1.3", + "jquery": "^3.3.1", + "popper.js": "^1.14.4" + }, + "devDependencies": { + "autoprefixer": "^9.2.1", + "bootswatch": "^4.1.3", + "copy-webpack-plugin": "^4.5.3", + "css-loader": "^1.0.0", + "extract-text-webpack-plugin": "^4.0.0-beta.0", + "html-webpack-plugin": "^3.2.0", + "node-sass": "^4.9.4", + "postcss-loader": "^3.0.0", + "sass-loader": "^7.1.0", + "style-loader": "^0.23.1", + "webpack": "^4.21.0", + "webpack-cli": "^3.1.2" + } +} diff --git a/src/main.rs b/src/main.rs index 368ecfc..11ebe91 100644 --- a/src/main.rs +++ b/src/main.rs @@ -57,9 +57,6 @@ pub struct Opt { /// Base directory #[structopt(parse(from_os_str))] base: PathBuf, - /// Template directory - #[structopt(parse(from_os_str))] - templates: PathBuf, /// Port and address to listen on. #[structopt(short = "l", long = "listen", default_value = "0.0.0.0:8080")] listen: String, @@ -75,10 +72,6 @@ fn main() { panic!("Base directory must be absolute"); } - if !opt.templates.is_absolute() { - panic!("Template directory must be absolute"); - } - let db = Filesystem::new(opt.base.clone()).unwrap(); web::serve(&opt, Polymorphic::Filesystem(db)).unwrap(); } diff --git a/src/web/mod.rs b/src/web/mod.rs index 844056f..6f9981d 100644 --- a/src/web/mod.rs +++ b/src/web/mod.rs @@ -1,12 +1,15 @@ use rocket; -use rocket::Outcome; +use rocket::{State, Outcome}; use rocket::http::Status; use rocket::request::{self, Request, FromRequest}; use rocket::response::content; use rocket::response::status::Custom; use rocket::http::uri::URI; +use rocket::response::NamedFile; +use rocket::fairing::AdHoc; use rocket_contrib::Template; +use std::path::{Path, PathBuf}; mod upload; @@ -47,6 +50,8 @@ mod templates { } } +struct StaticDir(String); + impl<'a, 'r> FromRequest<'a, 'r> for queries::Key { type Error = (); @@ -190,6 +195,11 @@ fn confirm(db: rocket::State, token: String) } } +#[get("/static/")] +fn files(file: PathBuf, static_dir: State) -> Option { + NamedFile::open(Path::new(&static_dir.0).join(file)).ok() +} + #[get("/")] fn root() -> Template { use std::collections::HashMap; @@ -220,7 +230,8 @@ pub fn serve(opt: &Opt, db: Polymorphic) -> Result<()> { .port(port) .workers(2) .root(opt.base.join("public")) - .extra("template_dir", format!("{}", opt.templates.display())) + .extra("template_dir", format!("{}/templates", opt.base.display())) + .extra("static_dir", format!("{}/public", opt.base.display())) .finalize()?; let routes = routes![ upload::multipart_upload, @@ -228,11 +239,20 @@ pub fn serve(opt: &Opt, db: Polymorphic) -> Result<()> { verify, delete, confirm, - root + root, + files, ]; rocket::custom(config, opt.verbose) .attach(Template::fairing()) + .attach(AdHoc::on_attach(|rocket| { + let static_dir = rocket.config() + .get_str("static_dir") + .unwrap() + .to_string(); + + Ok(rocket.manage(StaticDir(static_dir))) + })) .mount("/", routes) .manage(db) .launch(); diff --git a/templates/layout.html.hbs b/templates/layout.html.hbs deleted file mode 100644 index 00782bb..0000000 --- a/templates/layout.html.hbs +++ /dev/null @@ -1,10 +0,0 @@ - - - - Garbage Pile Public Key Server - - - - {{> @partial-block }} - - diff --git a/templates/confirm.html.hbs b/web/confirm.html.hbs similarity index 100% rename from templates/confirm.html.hbs rename to web/confirm.html.hbs diff --git a/templates/delete.html.hbs b/web/delete.html.hbs similarity index 100% rename from templates/delete.html.hbs rename to web/delete.html.hbs diff --git a/templates/index.html.hbs b/web/index.html.hbs similarity index 76% rename from templates/index.html.hbs rename to web/index.html.hbs index 71fecd9..a2c1715 100644 --- a/templates/index.html.hbs +++ b/web/index.html.hbs @@ -1,6 +1,6 @@ {{#> layout }} -

Garbage Pile Public Key Server

-

The verifying PGP key server. Powered by p≡pnology! +

Garbage Pile Public Key Server

+

The verifying PGP key server. Powered by p≡pnology!

Search for keys

diff --git a/web/index.js b/web/index.js new file mode 100644 index 0000000..2650d75 --- /dev/null +++ b/web/index.js @@ -0,0 +1,2 @@ +import 'bootstrap'; +import './index.scss'; diff --git a/web/index.scss b/web/index.scss new file mode 100644 index 0000000..c3f0a77 --- /dev/null +++ b/web/index.scss @@ -0,0 +1,3 @@ +@import "~bootswatch/dist/simplex/variables"; +@import "~bootstrap/scss/bootstrap"; +@import "~bootswatch/dist/simplex/bootswatch"; diff --git a/web/layout.html.hbs b/web/layout.html.hbs new file mode 100644 index 0000000..b9feccc --- /dev/null +++ b/web/layout.html.hbs @@ -0,0 +1,57 @@ + + + + + + + Garbage Pile Public Key Server + + + +
+ +
+
+
+
+ {{> @partial-block }} +
+
+
+
+ + diff --git a/templates/upload.html.hbs b/web/upload.html.hbs similarity index 100% rename from templates/upload.html.hbs rename to web/upload.html.hbs diff --git a/templates/verify.html.hbs b/web/verify.html.hbs similarity index 100% rename from templates/verify.html.hbs rename to web/verify.html.hbs diff --git a/webpack.config.js b/webpack.config.js new file mode 100644 index 0000000..f52c765 --- /dev/null +++ b/webpack.config.js @@ -0,0 +1,55 @@ +const path = require('path'); +const html = require('html-webpack-plugin'); +const text = require('extract-text-webpack-plugin'); +const copy = require('copy-webpack-plugin') + +module.exports = { + mode: 'production', + entry: './web/index.js', + output: { + filename: 'site.js', + path: path.resolve(__dirname, 'dist', 'public'), + publicPath: '/static' + }, + module: { + rules: [ + { + test:/\.(s*)css$/, + use: text.extract({ + fallback: 'style-loader', + use: [ + 'css-loader', + 'sass-loader', + { + loader: 'postcss-loader', + options: { + plugins: function () { // post css plugins, can be exported to postcss.config.js + return [ + require('autoprefixer') + ]; + } + } + } + ] + }) + } + ] + }, + plugins: [ + new html({ + filename: '../templates/layout.html.hbs', + template: 'web/layout.html.hbs', + }), + new text({ + filename: 'site.css' + }), + new copy([ + { + from: 'web/*.html.hbs', + to: path.resolve(__dirname, 'dist', "templates"), + ignore: [ 'layout.html.hbs' ], + flatten: true + } + ]) + ] +};