diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Crater/Gallery.rakumod | 25 | ||||
-rw-r--r-- | lib/Crater/Routes.rakumod | 24 | ||||
-rw-r--r-- | lib/Crater/Routes/Auth.rakumod | 34 | ||||
-rw-r--r-- | lib/Crater/Routes/Gallery.rakumod | 25 | ||||
-rw-r--r-- | lib/Crater/Service.rakumod | 52 | ||||
-rw-r--r-- | lib/Crater/Session.rakumod | 7 |
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; |