From 5df89f5057cc05deb8280f529a7aa33b2879f8cb Mon Sep 17 00:00:00 2001 From: Kaitlyn Parkhurst Date: Sat, 10 Jul 2021 21:28:09 -0700 Subject: [PATCH] Make UserManagement like everything else. --- Web/lib/MeshMage/Web.pm | 29 +- Web/lib/MeshMage/Web/Controller/Auth.pm | 76 +++++ Web/lib/MeshMage/Web/Plugin/UserManagement.pm | 94 ------ .../{first.html.tx => auth/init.html.tx} | 2 +- Web/templates/{ => auth}/login.html.tx | 2 +- Web/templates/login.html.tx.bak | 286 ------------------ 6 files changed, 93 insertions(+), 396 deletions(-) create mode 100644 Web/lib/MeshMage/Web/Controller/Auth.pm delete mode 100644 Web/lib/MeshMage/Web/Plugin/UserManagement.pm rename Web/templates/{first.html.tx => auth/init.html.tx} (93%) rename Web/templates/{ => auth}/login.html.tx (91%) delete mode 100644 Web/templates/login.html.tx.bak diff --git a/Web/lib/MeshMage/Web.pm b/Web/lib/MeshMage/Web.pm index fb6b043..73a8aaf 100644 --- a/Web/lib/MeshMage/Web.pm +++ b/Web/lib/MeshMage/Web.pm @@ -43,18 +43,11 @@ sub startup ($self) { $self->plugin( 'MeshMage::Web::Plugin::MinionTasks' ); $self->plugin( 'MeshMage::Web::Plugin::Helpers' ); - # Router + # Standard router. my $r = $self->routes; - - # Handle user login & first account creation. - # Routes: - # /login GET view_login, POST post_login - # /first GET view_first, POST post_first - # /logout GET logout, - $self->plugin( 'MeshMage::Web::Plugin::UserManagement' => { } ); - - # Ensure that only authenticated users can access routes under - # $auth. + + # Create a router chain that ensures the request is from an authenticated + # user. my $auth = $r->under( '/' => sub ($c) { # Login via session cookie. @@ -65,14 +58,22 @@ sub startup ($self) { $c->stash->{person} = $person; return 1; } - $c->redirect_to( $c->url_for( 'view_login' ) ); + $c->redirect_to( $c->url_for( 'auth_login' ) ); return undef; } - $c->redirect_to( $c->url_for( 'view_login' ) ); + $c->redirect_to( $c->url_for( 'auth_login' ) ); return undef; }); - + + # Controllers to handle initial user creation, login and logout. + $r->get ('/auth/init' )->to('Auth#init' )->name('auth_init' ); + $r->post('/auth/init' )->to('Auth#create_init' )->name('create_auth_init' ); + $r->get ('/auth/login' )->to('Auth#login' )->name('auth_login' ); + $r->post('/auth/login' )->to('Auth#create_login')->name('create_auth_login'); + $r->get ('/auth/logout')->to('Auth#logout' )->name('logout' ); + + # The /minion stuff is handled here because we needed to place it under $auth. $self->plugin( 'Minion::Admin' => { route => $auth->under( '/minion' ) } ); # Send requests for / to the dashboard. diff --git a/Web/lib/MeshMage/Web/Controller/Auth.pm b/Web/lib/MeshMage/Web/Controller/Auth.pm new file mode 100644 index 0000000..045bfdc --- /dev/null +++ b/Web/lib/MeshMage/Web/Controller/Auth.pm @@ -0,0 +1,76 @@ +package MeshMage::Web::Controller::Auth; +use Mojo::Base 'Mojolicious::Controller', -signatures; +use Try::Tiny; + +sub init ($c) { + my $user_count = $c->db->resultset('Person')->count; + if ( $user_count >= 1 ) { + $c->redirect_to( $c->url_for( 'auth_login' ) ); + return; + } +} + +sub create_init ($c) { + # This code should only run when there are no user accounts, if + # a user account exists, redirect the user to the login panel. + my $user_count = $c->db->resultset('Person')->count; + if ( $user_count >= 1 ) { + $c->redirect_to( $c->url_for( 'view_login' ) ); + return; + } + + my $person = try { + $c->db->storage->schema->txn_do( sub { + my $person = $c->db->resultset('Person')->create({ + email => $c->param('email'), + name => $c->param('name'), + }); + $person->new_related('auth_password', {})->set_password($c->param('password')); + return $person; + }); + } catch { + push @{$c->stash->{errors}}, "Account could not be created: $_"; + return; + }; + + $c->session->{uid} = $person->id; + + $c->redirect_to( $c->url_for( 'dashboard' ) ); +} + +sub login ($c) { + # If we have no user accounts, redirect the user to the + # initial create user page. + my $user_count = $c->db->resultset('Person')->count; + if ( $user_count == 0 ) { + $c->redirect_to( $c->url_for( 'auth_init' ) ); + return; + } +} + +sub create_login ($c) { + my $email = $c->stash->{form_email} = $c->param('email'); + my $password = $c->stash->{form_password} = $c->param('password'); + + my $person = $c->db->resultset('Person')->find( { email => $email } ) + or push @{$c->stash->{errors}}, "Invalid email address or password."; + + return if $c->stash->{errors}; + + $person->auth_password->check_password( $password ) + or push @{$c->stash->{errors}}, "Invalid email address or password."; + + return if $c->stash->{errors}; + + $c->session->{uid} = $person->id; + + $c->redirect_to( $c->url_for( 'dashboard' ) ); +} + +sub logout ($c) { + undef $c->session->{uid}; + $c->redirect_to( $c->url_for( 'auth_login' ) ); + +} + +1; diff --git a/Web/lib/MeshMage/Web/Plugin/UserManagement.pm b/Web/lib/MeshMage/Web/Plugin/UserManagement.pm deleted file mode 100644 index d86c1cd..0000000 --- a/Web/lib/MeshMage/Web/Plugin/UserManagement.pm +++ /dev/null @@ -1,94 +0,0 @@ -package MeshMage::Web::Plugin::UserManagement; -use Mojo::Base 'Mojolicious::Plugin', -signatures; -use Try::Tiny; - -sub register ( $self, $app, $config ) { - - my $r = $config->{route} || $app->routes; - - # User Management - $r->get ( '/first' )->to( cb => sub ($c) { - my $user_count = $c->db->resultset('Person')->count; - if ( $user_count >= 1 ) { - $c->redirect_to( $c->url_for( 'view_login' ) ); - return; - } - $c->render( template => 'first', format => 'html', handler => 'tx' ); - })->name( 'view_first' ); - - $r->post( '/first' )->to( cb => sub ($c) { - - # This code should only run when there are no user accounts, if - # a user account exists, redirect the user to the login panel. - my $user_count = $c->db->resultset('Person')->count; - if ( $user_count >= 1 ) { - $c->redirect_to( $c->url_for( 'view_login' ) ); - return; - } - - my $person = try { - $c->db->storage->schema->txn_do( sub { - my $person = $c->db->resultset('Person')->create({ - email => $c->param('email'), - name => $c->param('name'), - }); - $person->new_related('auth_password', {})->set_password($c->param('password')); - return $person; - }); - } catch { - push @{$c->stash->{errors}}, "Account could not be created: $_"; - $c->render( template => 'first', format => 'html', handler => 'tx' ); - return; - }; - - $c->session->{uid} = $person->id; - - $c->redirect_to( $c->url_for( 'dashboard' ) ); - - })->name( 'post_first' ); - - $r->get ( '/login' )->to( cb => sub ($c) { - - # If we have no user accounts, redirect the user to the - # initial create user page. - my $user_count = $c->db->resultset('Person')->count; - if ( $user_count == 0 ) { - $c->redirect_to( $c->url_for( 'view_first' ) ); - return; - } - - $c->render( template => 'login', format => 'html', handler => 'tx' ); - })->name( 'view_login' ); - - $r->post( '/login' )->to( cb => sub ($c) { - my $email = $c->stash->{form_email} = $c->param('email'); - my $password = $c->stash->{form_password} = $c->param('password'); - - my $person = $c->db->resultset('Person')->find( { email => $email } ) - or push @{$c->stash->{errors}}, "Invalid email address or password."; - - if ( $c->stash->{errors} or not $person ) { - $c->render( template => 'login', format => 'html', handler => 'tx' ); - return; - } - - $person->auth_password->check_password( $password ) - or push @{$c->stash->{errors}}, "Invalid email address or password."; - - if ( $c->stash->{errors} ) { - $c->render( template => 'login', format => 'html', handler => 'tx' ); - return; - } - - $c->session->{uid} = $person->id; - - $c->redirect_to( $c->url_for( 'dashboard' ) ); - })->name( 'post_login' ); - - $r->get ( '/logout' )->to( cb => sub ($c) { - undef $c->session->{uid}; - $c->redirect_to( $c->url_for( 'view_login' ) ); - })->name( 'logout' ); -} - -1; diff --git a/Web/templates/first.html.tx b/Web/templates/auth/init.html.tx similarity index 93% rename from Web/templates/first.html.tx rename to Web/templates/auth/init.html.tx index baabb25..0ce3149 100644 --- a/Web/templates/first.html.tx +++ b/Web/templates/auth/init.html.tx @@ -16,7 +16,7 @@ %% } -
+ %% include '_base/form/input.tx' { type => 'text', name => 'name', %% title => 'Your name', diff --git a/Web/templates/login.html.tx b/Web/templates/auth/login.html.tx similarity index 91% rename from Web/templates/login.html.tx rename to Web/templates/auth/login.html.tx index 44343a7..6f5cf88 100644 --- a/Web/templates/login.html.tx +++ b/Web/templates/auth/login.html.tx @@ -16,7 +16,7 @@ %% } - + %% include '_base/form/input.tx' { type => 'email', name => 'email', %% title => 'Email Address', diff --git a/Web/templates/login.html.tx.bak b/Web/templates/login.html.tx.bak deleted file mode 100644 index 3641dbf..0000000 --- a/Web/templates/login.html.tx.bak +++ /dev/null @@ -1,286 +0,0 @@ - - - - - - - - - Dashboard Template ยท Bootstrap v5.0 - - - - - - - - - - - - - - - - - - - - - -
-
- - -
-
-

Dashboard

-
-
- - -
- -
-
- - - -

Section title

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#HeaderHeaderHeaderHeader
1,001randomdataplaceholdertext
1,002placeholderirrelevantvisuallayout
1,003datarichdashboardtabular
1,003informationplaceholderillustrativedata
1,004textrandomlayoutdashboard
1,005dashboardirrelevanttextplaceholder
1,006dashboardillustrativerichdata
1,007placeholdertabularinformationirrelevant
1,008randomdataplaceholdertext
1,009placeholderirrelevantvisuallayout
1,010datarichdashboardtabular
1,011informationplaceholderillustrativedata
1,012textplaceholderlayoutdashboard
1,013dashboardirrelevanttextvisual
1,014dashboardillustrativerichdata
1,015randomtabularinformationtext
-
-
-
-
- - - - - - - - - -