summary refs log tree commit diff stats
path: root/lib/Crater
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Crater')
-rw-r--r--lib/Crater/Gallery.rakumod25
-rw-r--r--lib/Crater/Routes.rakumod24
-rw-r--r--lib/Crater/Routes/Auth.rakumod34
-rw-r--r--lib/Crater/Routes/Gallery.rakumod25
-rw-r--r--lib/Crater/Service.rakumod52
-rw-r--r--lib/Crater/Session.rakumod7
6 files changed, 167 insertions, 0 deletions
diff --git a/lib/Crater/Gallery.rakumod b/lib/Crater/Gallery.rakumod
new file mode 100644
index 0000000..ea92c47
--- /dev/null
+++ b/lib/Crater/Gallery.rakumod
@@ -0,0 +1,25 @@
+class Crater::Gallery {
+    has IO $.directory is required;
+
+    method list() {
+        my @gallery;
+        for dir($!directory).sort(*.modified) {
+            if .IO.d {
+
+            } elsif .IO.f {
+                my Str $ext = .extension.lc;
+                if $ext eq "jpg"|"png" {
+                    push @gallery, %( :type<img>, :src($_.relative($!directory)) );
+                } elsif $ext eq "0" {
+                    push @gallery, %( :type<heading>, :text($_.slurp) );
+                } elsif $ext eq "txt" {
+                    push @gallery, %( :type<text>, :text($_.slurp) );
+                } else {
+                    warn "Unhandled file :$_";
+                }
+            }
+        }
+
+        return @gallery;
+    }
+}
diff --git a/lib/Crater/Routes.rakumod b/lib/Crater/Routes.rakumod
new file mode 100644
index 0000000..6206e5c
--- /dev/null
+++ b/lib/Crater/Routes.rakumod
@@ -0,0 +1,24 @@
+use Cro::HTTP::Router;
+use Cro::WebApp::Template;
+
+use Crater::Gallery;
+use Crater::Routes::Auth;
+use Crater::Routes::Gallery;
+
+sub routes(
+    Crater::Gallery :$gallery!, #= gallery object
+    Str :$password!, #= password for authentication
+) is export {
+    template-location 'templates/';
+
+    route {
+        after { redirect '/login', :see-other if .status == 401 };
+
+        include auth-routes(:$password);
+        include gallery-routes(:$gallery);
+
+        get -> 'resources', 'css', *@path {
+            static 'resources', 'css', @path;
+        }
+    }
+}
diff --git a/lib/Crater/Routes/Auth.rakumod b/lib/Crater/Routes/Auth.rakumod
new file mode 100644
index 0000000..23872e9
--- /dev/null
+++ b/lib/Crater/Routes/Auth.rakumod
@@ -0,0 +1,34 @@
+use Cro::HTTP::Router;
+use Cro::WebApp::Template;
+
+use Crater::Session;
+
+sub auth-routes(
+    Str :$password!, #= password for authentication
+) is export {
+    route {
+        get -> LoggedIn $session, 'login' {
+            redirect '/', :see-other;
+        }
+        get -> Crater::Session $session, 'login' {
+            template 'login.crotmp', { :!error };
+        }
+
+        post -> Crater::Session $session, 'login' {
+            request-body -> (:$pass!, *%) {
+                if $password eq $pass {
+                    $session.logged-in = True;
+                    redirect :see-other, '/';
+                } else {
+                    template 'login.crotmp', {
+                        error => 'Incorrect password.'
+                    };
+                }
+            }
+        }
+        get -> Crater::Session $session, 'logout' {
+            $session.logged-in = False;
+            redirect :see-other, '/';
+        }
+    }
+}
diff --git a/lib/Crater/Routes/Gallery.rakumod b/lib/Crater/Routes/Gallery.rakumod
new file mode 100644
index 0000000..04c8d74
--- /dev/null
+++ b/lib/Crater/Routes/Gallery.rakumod
@@ -0,0 +1,25 @@
+use Cro::HTTP::Router;
+use Cro::WebApp::Template;
+
+use Crater::Gallery;
+use Crater::Session;
+
+sub gallery-routes(
+    Crater::Gallery :$gallery!, #= gallery object
+) is export {
+    route {
+        get -> LoggedIn $session {
+            template 'gallery.crotmp', {
+                gallery => $gallery.list(),
+                title => "Gallery"
+            };
+        }
+
+        get -> {
+            redirect '/login', :see-other;
+        }
+        get -> *@path {
+            static $gallery.directory, @path;
+        }
+    }
+}
diff --git a/lib/Crater/Service.rakumod b/lib/Crater/Service.rakumod
new file mode 100644
index 0000000..c0bdd7a
--- /dev/null
+++ b/lib/Crater/Service.rakumod
@@ -0,0 +1,52 @@
+use Config::TOML;
+
+use Cro::HTTP::Server;
+use Cro::HTTP::Log::File;
+use Cro::HTTP::Session::InMemory;
+
+use Crater::Routes;
+use Crater::Gallery;
+use Crater::Session;
+
+#| Crater is a photo gallery
+sub MAIN(
+    IO() :$config where *.IO.f = 'resources/config.toml', #= configuration file
+    IO() :$directory! where *.IO.d, #= gallery directory (takes absolute path)
+    Str :$password = '0x', #= password for authentication
+    Bool :$verbose, #= increase verbosity
+) is export {
+    put "Initialized: {now - INIT now}";
+    put "Gallery: {$directory.absolute}";
+
+    my %conf = from-toml($config.slurp);
+    %conf<server><host> //= %*ENV<CRATER_HOST>;
+    %conf<server><port> //= %*ENV<CRATER_PORT>;
+
+    my Crater::Gallery $gallery = Crater::Gallery.new(:$directory);
+
+    my Cro::Service $http = Cro::HTTP::Server.new(
+        http => <1.1>,
+        host => %conf<server><host> || die("host not set"),
+        port => %conf<server><port> || die("port not set"),
+        application => routes(:$password, :$gallery),
+        before => [
+                   Cro::HTTP::Session::InMemory[Crater::Session].new(
+                       expiration => Duration.new(60 * 15)
+                   );
+               ],
+        after => [
+                  Cro::HTTP::Log::File.new(logs => $*OUT, errors => $*ERR)
+              ]
+    );
+
+    $http.start;
+    say "Listening at http://%conf<server><host>:%conf<server><port>";
+
+    react {
+        whenever signal(SIGINT) {
+            say "Shutting down...";
+            $http.stop;
+            done;
+        }
+    }
+}
diff --git a/lib/Crater/Session.rakumod b/lib/Crater/Session.rakumod
new file mode 100644
index 0000000..246c8bb
--- /dev/null
+++ b/lib/Crater/Session.rakumod
@@ -0,0 +1,7 @@
+use Cro::HTTP::Auth;
+
+class Crater::Session does Cro::HTTP::Auth {
+    has Bool $.logged-in is rw;
+}
+
+subset LoggedIn of Crater::Session is export where *.logged-in;