From 7b598a9bba236f88f32d0abf7dc785e9daf7909a Mon Sep 17 00:00:00 2001 From: Kaitlyn Parkhurst Date: Tue, 6 Sep 2022 19:24:59 -0700 Subject: [PATCH] Initial Web app. --- Web/cpanfile | 4 ++ Web/lib/MJB/Web.pm | 66 +++++++++++++++++++++++++++ Web/lib/MJB/Web/Command/db_dump.pm | 29 ++++++++++++ Web/lib/MJB/Web/Command/dbc.pm | 31 +++++++++++++ Web/lib/MJB/Web/Command/flip_admin.pm | 32 +++++++++++++ Web/script/mjb | 10 ++++ 6 files changed, 172 insertions(+) create mode 100644 Web/cpanfile create mode 100644 Web/lib/MJB/Web.pm create mode 100644 Web/lib/MJB/Web/Command/db_dump.pm create mode 100644 Web/lib/MJB/Web/Command/dbc.pm create mode 100644 Web/lib/MJB/Web/Command/flip_admin.pm create mode 100755 Web/script/mjb diff --git a/Web/cpanfile b/Web/cpanfile new file mode 100644 index 0000000..dac8feb --- /dev/null +++ b/Web/cpanfile @@ -0,0 +1,4 @@ +requires 'Mojolicious'; +requires 'Mojo::Pg'; +requires 'Mojo::File'; +requires 'DateTime::Format::Pg'; diff --git a/Web/lib/MJB/Web.pm b/Web/lib/MJB/Web.pm new file mode 100644 index 0000000..e998fdb --- /dev/null +++ b/Web/lib/MJB/Web.pm @@ -0,0 +1,66 @@ +package MJB::Web; +use Mojo::Base 'Mojolicious', -signatures; +use MJB::DB; + +sub startup ($self) { + my $config = $self->plugin('NotYAMLConfig', { file => -e 'mjb.yml' + ? 'mjb.yml' + : '/etc/mjb.yml' + }); + + # Configure the application + $self->secrets($config->{secrets}); + + # Set the cookie expires to 30 days. + $self->sessions->default_expiration(2592000); + + # Load our custom commands. + push @{$self->commands->namespaces}, 'MJB::Web::Command'; + + $self->helper( db => sub { + return state $db = WeightGrapher::DB->connect($config->{database}->{mjb}); + }); + + # Standard router. + my $r = $self->routes->under( '/' => sub ($c) { + + # If the user has a uid session cookie, then load their user account. + if ( $c->session('uid') ) { + my $person = $c->db->resultset('Person')->find( $c->session('uid') ); + if ( $person && $person->is_enabled ) { + $c->stash->{person} = $person; + } + } + + return 1; + }); + + # Create a router chain that ensures the request is from an authenticated user. + my $auth = $r->under( '/' => sub ($c) { + + # Logged in user exists. + if ( $c->stash->{person} ) { + return 1; + } + + # No user account for this seession. + $c->redirect_to( $c->url_for( 'show_login' ) ); + return undef; + }); + + # Create a router chain that ensures the request is from an admin user. + my $admin = $auth->under( '/' => sub ($c) { + + # Logged in user exists. + if ( $c->stash->{person}->is_admin ) { + return 1; + } + + # No user account for this seession. + $c->redirect_to( $c->url_for( 'show_dashboard' ) ); + return undef; + }); +} + +1; + diff --git a/Web/lib/MJB/Web/Command/db_dump.pm b/Web/lib/MJB/Web/Command/db_dump.pm new file mode 100644 index 0000000..3c1c9fd --- /dev/null +++ b/Web/lib/MJB/Web/Command/db_dump.pm @@ -0,0 +1,29 @@ +package MJB::Web::Command::db_dump; +use Mojo::Base 'Mojolicious::Command'; +use DBIx::Class::Schema::Config; + +use Mojo::Util qw( getopt ); + +has description => 'Dump the mjb database.'; +has usage => "$0 dbc"; + +sub run { + my ( $self, @args ) = @_; + + my $db_conf = DBIx::Class::Schema::Config->coerce_credentials_from_mojolike( + DBIx::Class::Schema::Config->_make_connect_attrs( + $self->app->config->{database}{mjb} + ) + ); + + if ( $db_conf->{dsn} =~ /^dbi:Pg:dbname=([^;]+);host=([^;]+)$/ ) { + $db_conf->{dbname} = $1; + $db_conf->{hostname} = $2; + } + + $ENV{PGPASSWORD} = $db_conf->{password}; + exec 'pg_dump', '-h', $db_conf->{hostname}, '-U', $db_conf->{user}, $db_conf->{dbname}; + +} + +1; diff --git a/Web/lib/MJB/Web/Command/dbc.pm b/Web/lib/MJB/Web/Command/dbc.pm new file mode 100644 index 0000000..147a5a1 --- /dev/null +++ b/Web/lib/MJB/Web/Command/dbc.pm @@ -0,0 +1,31 @@ +package MJB::Web::Command::dbc; +use Mojo::Base 'Mojolicious::Command'; +use DBIx::Class::Schema::Config; + +use Mojo::Util qw( getopt ); + +has description => 'Connect to the DB as if running psql.'; +has usage => "$0 dbc"; + + +sub run { + my ( $self, @args ) = @_; + + my $db_conf = DBIx::Class::Schema::Config->coerce_credentials_from_mojolike( + DBIx::Class::Schema::Config->_make_connect_attrs( + $self->app->config->{database}{mjb} + ) + ); + + if ( $db_conf->{dsn} =~ /^dbi:Pg:dbname=([^;]+);host=([^;]+)$/ ) { + $db_conf->{dbname} = $1; + $db_conf->{hostname} = $2; + } + + $ENV{PGPASSWORD} = $db_conf->{password}; + exec 'psql', '-h', $db_conf->{hostname}, '-U', $db_conf->{user}, $db_conf->{dbname}; + +} + +1; + diff --git a/Web/lib/MJB/Web/Command/flip_admin.pm b/Web/lib/MJB/Web/Command/flip_admin.pm new file mode 100644 index 0000000..444d1eb --- /dev/null +++ b/Web/lib/MJB/Web/Command/flip_admin.pm @@ -0,0 +1,32 @@ +package MJB::Web::Command::flip_admin; +use Mojo::Base 'Mojolicious::Command'; +use DBIx::Class::Schema::Config; + +use Mojo::Util qw( getopt ); + +has description => "Flip a user's admin bit."; +has usage => "$0 flip_admin email\@domain.comi\n"; + +sub run { + my ( $self, $email ) = @_; + + die "Error: you must provide an email address.\n" + unless $email; + + my $person = $self->app->db->person( { email => $email } ); + + die "Error: couldn't find anyone with the email $email?\n" + unless $person; + + if ( $person->is_admin ) { + $person->is_admin( 0 ); + print "That account was previously an admin. Now it is not.\n"; + } else { + $person->is_admin( 1 ); + print "$email is now an admin.\n"; + } + + $person->update; +} + +1; diff --git a/Web/script/mjb b/Web/script/mjb new file mode 100755 index 0000000..88ce4d9 --- /dev/null +++ b/Web/script/mjb @@ -0,0 +1,10 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +use Mojo::File qw(curfile); +use lib curfile->dirname->sibling('lib')->to_string; +use Mojolicious::Commands; + +# Start command line interface for application +Mojolicious::Commands->start_app('MJB::Web');