From dc9a42f0e68594e6534ca1e9c6dd94e06ba3b8d6 Mon Sep 17 00:00:00 2001 From: ngoomie Date: Tue, 9 May 2023 00:37:07 -0600 Subject: [PATCH] Add logout, POD documentation, various organizational things, et al a bunch of POD documentation was addded to various .pm files `CharmBoard::Controller::Auth` has been split into `CharmBoard::Controller::Register`, `CharmBoard::Controller::Login`, and `CharmBoard::Controller:Logout` (that last one is new, too!) `Main.pm` has been renamed to `Index.pm` like it was in the beginning the config value `board_name` now works `CharmBoard::Schema` namespaces were changed (`ResultSource` is now `Source`, `ResultSet` is now `Set`) templates were mildly reorganized almost switched from EPL to HAML. decided I really shouldn't because I utterly despise anything whitespace sensitive, so it doesn't matter how compact HAML is in comparison! --- .gitignore | 3 - charmboard.example.conf | 2 +- lib/CharmBoard.pm | 74 +++++++--- lib/CharmBoard/Controller/Auth.pm | 139 ------------------ lib/CharmBoard/Controller/Index.pm | 11 ++ lib/CharmBoard/Controller/Login.pm | 76 ++++++++++ lib/CharmBoard/Controller/Logout.pm | 15 ++ lib/CharmBoard/Controller/Main.pm | 7 - lib/CharmBoard/Controller/Register.pm | 79 ++++++++++ lib/CharmBoard/Crypt/Password.pm | 45 +++++- lib/CharmBoard/Crypt/Seasoning.pm | 1 + lib/CharmBoard/Schema.pm | 4 +- .../Schema/{Result => Source}/Categories.pm | 2 +- .../Schema/{Result => Source}/Posts.pm | 10 +- .../Schema/{Result => Source}/Session.pm | 4 +- .../Schema/{Result => Source}/Subforums.pm | 5 +- .../Schema/{Result => Source}/Threads.pm | 7 +- .../Schema/{Result => Source}/Users.pm | 3 +- templates/index.html.ep | 6 +- templates/layouts/_header.html.ep | 2 - templates/layouts/default.html.ep | 4 +- .../layouts/{ => default}/_footer.html.ep | 0 templates/layouts/default/_header.html.ep | 14 ++ templates/login.html.ep | 2 +- templates/register.html.ep | 2 +- 25 files changed, 320 insertions(+), 197 deletions(-) delete mode 100644 lib/CharmBoard/Controller/Auth.pm create mode 100644 lib/CharmBoard/Controller/Index.pm create mode 100644 lib/CharmBoard/Controller/Login.pm create mode 100644 lib/CharmBoard/Controller/Logout.pm delete mode 100644 lib/CharmBoard/Controller/Main.pm create mode 100644 lib/CharmBoard/Controller/Register.pm rename lib/CharmBoard/Schema/{Result => Source}/Categories.pm (87%) rename lib/CharmBoard/Schema/{Result => Source}/Posts.pm (74%) rename lib/CharmBoard/Schema/{Result => Source}/Session.pm (90%) rename lib/CharmBoard/Schema/{Result => Source}/Subforums.pm (84%) rename lib/CharmBoard/Schema/{Result => Source}/Threads.pm (71%) rename lib/CharmBoard/Schema/{Result => Source}/Users.pm (94%) delete mode 100644 templates/layouts/_header.html.ep rename templates/layouts/{ => default}/_footer.html.ep (100%) create mode 100644 templates/layouts/default/_header.html.ep diff --git a/.gitignore b/.gitignore index 94361a9..05af134 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,6 @@ # CharmBoard-specific charmboard.conf -# Mojolicious examples to be nuked later -t/basic.t - # SQLite *.db *.db-* \ No newline at end of file diff --git a/charmboard.example.conf b/charmboard.example.conf index c827b77..2a57439 100644 --- a/charmboard.example.conf +++ b/charmboard.example.conf @@ -1,5 +1,5 @@ { - board_name => '', # this doesn't do anything yet + board_name => '', database => { type => '', # 'sqlite' or 'mysql' diff --git a/lib/CharmBoard.pm b/lib/CharmBoard.pm index f6c438b..c32d7ac 100644 --- a/lib/CharmBoard.pm +++ b/lib/CharmBoard.pm @@ -1,67 +1,105 @@ package CharmBoard; +use utf8; use experimental 'try', 'smartmatch'; use Mojo::Base 'Mojolicious', -signatures; use CharmBoard::Schema; +=pod +=head1 NAME +CharmBoard - revive the fun posting experience! +=head1 NOTES +This documentation is intended for prospective code +contributors. If you're looking to set CharmBoard up, +look for the Markdown format (.md) documentation instead. + +CharmBoard uses a max line length of 60 chars and a tab +size of two spaces. +=head1 DESCRIPTION +CharmBoard is forum software written in Perl with +Mojolicious, intended to be a more fun alternative to the +bigger forum suites available today, inspired by older +forum software like AcmlmBoard, while also being more +modernized in terms of security practices than they are. +Customization ability is another important goal next to +making software that feels fun for the end user to use. +=cut + # this method will run once at server start -sub startup ($app) { +sub startup ($self) { # load plugins that require no additional conf - $app->plugin('TagHelpers'); + $self->plugin('TagHelpers'); # load configuration from config file - my $config = $app->plugin('Config' => {file => 'charmboard.conf'}); + my $config = $self->plugin('Config' => + {file => 'charmboard.conf'}); + + # set this specific forum's name + $self->helper(boardName => sub {$config->{board_name}}); # load dev env only stuff, if applicable if ( $config->{environment} eq 'dev' ) { - $app->plugin('Renderer::WithoutCache'); - $app->renderer->cache->max_keys(0)}; + $self->plugin('Renderer::WithoutCache'); + $self->renderer->cache->max_keys(0)}; # import Mojolicious secrets - $app->secrets($config->{secrets}); + $self->secrets($config->{secrets}); # import password pepper value - $app->helper(pepper => sub {$config->{pass_crypt}->{pepper}}); + $self->helper(pepper => sub {$config->{pass_crypt}->{pepper}}); ## database setup + # ? this could maybe be a given/when my ($dsn, $dbUnicode); - if ($app->config->{database}->{type} ~~ 'sqlite') { + if ($self->config->{database}->{type} ~~ 'sqlite') { $dsn = "dbi:SQLite:" . $config->{database}->{name}; $dbUnicode = "sqlite_unicode"} - elsif ($app->config->{database}->{type} ~~ 'mysql') { + + elsif ($self->config->{database}->{type} ~~ 'mysql') { $dsn = "dbi:mysql:" . $config->{database}->{name}; $dbUnicode = "mysql_enable_utf"} - else {die "\nUnknown, unsupported, or empty database type in charmboard.conf. - If you're sure you've set it to something supported, maybe double check your spelling?\n + + else {die "\nUnknown, unsupported, or empty database type + in charmboard.conf. If you're sure you've set it to + something supported, maybe double check your spelling? + \n\n\t Valid options: 'sqlite', 'mysql'"}; + my $schema = CharmBoard::Schema->connect( $dsn, $config->{database}->{user}, $config->{database}->{pass}, {$dbUnicode => 1}); - $app->helper(schema => sub {$schema}); + $self->helper(schema => sub {$schema}); # router - my $r = $app->routes; + my $r = $self->routes; # controller routes ## index page $r->get('/')->to( - controller => 'Controller::Main', + controller => 'Controller::Index', action => 'index'); + ## registration page $r->get('/register')->to( - controller => 'Controller::Auth', + controller => 'Controller::Register', action => 'register'); $r->post('/register')->to( - controller => 'Controller::Auth', + controller => 'Controller::Register', action => 'register_do'); + ## login page $r->get('/login')->to( - controller => 'Controller::Auth', + controller => 'Controller::Login', action => 'login'); $r->post('/login')->to( - controller => 'Controller::Auth', + controller => 'Controller::Login', action => 'login_do'); + + ## logout + $r->get('/logout')->to( + controller => 'Controller::Logout', + action => 'logout_do') } 1; diff --git a/lib/CharmBoard/Controller/Auth.pm b/lib/CharmBoard/Controller/Auth.pm deleted file mode 100644 index ee2eefa..0000000 --- a/lib/CharmBoard/Controller/Auth.pm +++ /dev/null @@ -1,139 +0,0 @@ -package CharmBoard::Controller::Auth; -use experimental 'try', 'smartmatch'; -use Mojo::Base 'Mojolicious::Controller', -signatures; -use CharmBoard::Crypt::Password; -use CharmBoard::Crypt::Seasoning; - -# initial registration page -sub register ($app) { - $app->render( - template => 'register', - error => $app->flash('error'), - message => $app->flash('message'))}; - -# process submitted registration form -sub register_do ($app) { - my $username = $app->param('username'); - my $email = $app->param('email'); - my $password = $app->param('password'); - my $confirmPassword = $app->param('confirm-password'); - - my $catchError; - - # declare vars used through multiple try/catch blocks with - # 'our' so they work throughout the entire subroutine - our ($userCheck, $emailCheck, $salt, $hash); - - try { # make sure registration info is valid - # TODO: implement email validation here at some point - - # check to make sure all required fields are filled - ($username, $email, $password, $confirmPassword) ne undef - or die "Please fill out all required fields."; - - # check to make sure both passwords match - # TODO: add check on frontend for this for people with JS enabled - $password eq $confirmPassword - or die "Passwords do not match"; - - # check to make sure username and/or email isn't already in use; - # if not, continue with registration - ## search for input username and email in database - $userCheck = $app->schema->resultset('Users')->search({username => $username})->single; - $emailCheck = $app->schema->resultset('Users')->search({email => $email})->single; - - ($userCheck && $emailCheck) eq undef - or die "Username already in use.\nemail already in use."; - ($userCheck) eq undef - or die "Username already in use."; - ($emailCheck) eq undef - or die "email already in use."} - catch ($catchError) { - $app->flash(error => $catchError); - $app->redirect_to('register');} - - try { - $password = $app->pepper . ':' . $password; - # return hashed result + salt - ($salt, $hash) = passgen($password) or die; - - # add user info and pw/salt to DB - $app->schema->resultset('Users')->create({ - username => $username, - email => $email, - password => $hash, - salt => $salt, - signup_date => time }) or die; - - $app->flash(message => 'User registered successfully!'); - $app->redirect_to('register')} - catch ($catchError) { - print $catchError; - $app->flash(error => 'Your registration info was correct, - but a server error prevented you from registering. - This has been logged so your administrator can fix it.'); - $app->redirect_to('register')}}; - -sub login ($app) { - $app->render( - template => 'login', - error => $app->flash('error'), - message => $app->flash('message'))}; - -sub login_do ($app) { - my $username = $app->param('username'); - my $password = $app->pepper . ':' . $app->param('password'); - - my $catchError; - - # declare vars used through multiple try/catch blocks with - # 'our' so they work throughout the entire subroutine - our ($userInfo, $passCheck, $userID, $sessionKey); - - try { # check user credentials first - # check to see if user by entered username exists - $userInfo = $app->schema->resultset('Users')->search({username => $username}); - $userInfo or die; - - # now check password validity - $passCheck = passchk($userInfo->get_column('salt')->first, - $userInfo->get_column('password')->first, $password); - $passCheck or die;} - - catch ($catchError) { # redirect to login page on fail - print $catchError; - $app->flash(error => 'Username or password incorrect.'); - $app->redirect_to('login');} - - try { # now attempt to create session - # get user ID for session creation - $userID = $userInfo->get_column('user_id')->first; - - # gen session key - $sessionKey = seasoning(16); - - # add session to database - $app->schema->resultset('Session')->create({ - session_key => $sessionKey, - user_id => $userID, - session_expiry => time + 604800, - is_ip_bound => 0, - bound_ip => undef }) or die; - - # now create session cookie for user - $app->session(is_auth => 1); - $app->session(user_id => $userID); - $app->session(session_key => $sessionKey); - $app->session(expiration => 604800); - - # redirect to index upon success - $app->redirect_to('/')} - - catch ($catchError) { # redirect to login page on fail - print $catchError; - $app->flash(error => 'Your username and password were correct, - but a server error prevented you from logging in. - This has been logged so your administrator can fix it.'); - $app->redirect_to('login')}} - -1; \ No newline at end of file diff --git a/lib/CharmBoard/Controller/Index.pm b/lib/CharmBoard/Controller/Index.pm new file mode 100644 index 0000000..8f1ba0a --- /dev/null +++ b/lib/CharmBoard/Controller/Index.pm @@ -0,0 +1,11 @@ +package CharmBoard::Controller::Index; +use utf8; +use experimental 'try', 'smartmatch'; +use Mojo::Base 'Mojolicious::Controller', -signatures; + +sub index ($self) { + $self->render(template => 'index') + + } + +1; \ No newline at end of file diff --git a/lib/CharmBoard/Controller/Login.pm b/lib/CharmBoard/Controller/Login.pm new file mode 100644 index 0000000..acadd5f --- /dev/null +++ b/lib/CharmBoard/Controller/Login.pm @@ -0,0 +1,76 @@ +package CharmBoard::Controller::Login; +use utf8; +use experimental 'try', 'smartmatch'; +use Mojo::Base 'Mojolicious::Controller', -signatures; +use CharmBoard::Crypt::Password; +use CharmBoard::Crypt::Seasoning; + +=pod +=head1 NAME +CharmBoard::Controller::Login +=cut + +sub login ($self) { + $self->render( + template => 'login', + error => $self->flash('error'), + message => $self->flash('message'))}; + +sub login_do ($self) { + my $username = $self->param('username'); + my $password = $self->pepper . ':' . $self->param('password'); + + my $catchError; + + # declare vars used through multiple try/catch blocks with + # 'our' so they work throughout the entire subroutine + our ($userInfo, $passCheck, $userID, $sessionKey); + + try { # check user credentials first + # check to see if user by entered username exists + $userInfo = $self->schema->resultset('Users')->search( + {username => $username}); + $userInfo or die; + + # now check password validity + $passCheck = passchk($userInfo->get_column('salt')->first, + $userInfo->get_column('password')->first, $password); + $passCheck or die;} + + catch ($catchError) { # redirect to login page on fail + print $catchError; + $self->flash(error => 'Username or password incorrect.'); + $self->redirect_to('login');} + + try { # now attempt to create session + # get user ID for session creation + $userID = $userInfo->get_column('user_id')->first; + + # gen session key + $sessionKey = seasoning(16); + + # add session to database + $self->schema->resultset('Session')->create({ + session_key => $sessionKey, + user_id => $userID, + session_expiry => time + 604800, + is_ip_bound => 0, + bound_ip => undef }) or die; + + # now create session cookie for user + $self->session(is_auth => 1); + $self->session(user_id => $userID); + $self->session(session_key => $sessionKey); + $self->session(expiration => 604800); + + # redirect to index upon success + $self->redirect_to('/')} + + catch ($catchError) { # redirect to login page on fail + print $catchError; + $self->flash(error => 'Your username and password were correct, + but a server error prevented you from logging in. This has been + logged so the administrator can fix it.'); + $self->redirect_to('login')}} + +1; \ No newline at end of file diff --git a/lib/CharmBoard/Controller/Logout.pm b/lib/CharmBoard/Controller/Logout.pm new file mode 100644 index 0000000..aa6084a --- /dev/null +++ b/lib/CharmBoard/Controller/Logout.pm @@ -0,0 +1,15 @@ +package CharmBoard::Controller::Logout; +use utf8; +use experimental 'try', 'smartmatch'; +use Mojo::Base 'Mojolicious::Controller', -signatures; + +sub logout_do ($self) { + # destroy entry for this session in the database + $self->schema->resultset('Session')->search({ + session_key => $self->session('session_key')})->delete; + # now nuke the actual session cookie + $self->session(expires => 1); + # redirect to index + $self->redirect_to('/')} + +1; \ No newline at end of file diff --git a/lib/CharmBoard/Controller/Main.pm b/lib/CharmBoard/Controller/Main.pm deleted file mode 100644 index cc3cc65..0000000 --- a/lib/CharmBoard/Controller/Main.pm +++ /dev/null @@ -1,7 +0,0 @@ -package CharmBoard::Controller::Main; -use Mojo::Base 'Mojolicious::Controller', -signatures; - -sub index ($app) { - $app->render(template => 'index')} - -1; \ No newline at end of file diff --git a/lib/CharmBoard/Controller/Register.pm b/lib/CharmBoard/Controller/Register.pm new file mode 100644 index 0000000..3fdab24 --- /dev/null +++ b/lib/CharmBoard/Controller/Register.pm @@ -0,0 +1,79 @@ +package CharmBoard::Controller::Register; +use utf8; +use experimental 'try', 'smartmatch'; +use Mojo::Base 'Mojolicious::Controller', -signatures; +use CharmBoard::Crypt::Password; + +# initial registration page +sub register ($self) { + $self->render( + template => 'register', + error => $self->flash('error'), + message => $self->flash('message'))}; + +# process submitted registration form +sub register_do ($self) { + my $username = $self->param('username'); + my $email = $self->param('email'); + my $password = $self->param('password'); + my $confirmPassword = $self->param('confirm-password'); + + my $catchError; + + # declare vars used through multiple try/catch blocks with + # 'our' so they work throughout the entire subroutine + our ($userCheck, $emailCheck, $salt, $hash); + + try { # make sure registration info is valid + # TODO: implement email validation here at some point + + # check to make sure all required fields are filled + ($username, $email, $password, $confirmPassword) + or die "Please fill out all required fields."; + + # check to make sure both passwords match + # TODO: add check on frontend for this for people with JS enabled + $password eq $confirmPassword + or die "Passwords do not match"; + + # check to make sure username and/or email isn't already in use; + # if not, continue with registration + ## search for input username and email in database + $userCheck = $self->schema->resultset('Users')->search( + {username => $username})->single; + $emailCheck = $self->schema->resultset('Users')->search( + {email => $email})->single; + + ($userCheck && $emailCheck) eq undef + or die "Username already in use.\nemail already in use."; + ($userCheck) eq undef + or die "Username already in use."; + ($emailCheck) eq undef + or die "email already in use."} + catch ($catchError) { + $self->flash(error => $catchError); + $self->redirect_to('register');} + + try { + $password = $self->pepper . ':' . $password; + # return hashed result + salt + ($salt, $hash) = passgen($password) or die; + + # add user info and pw/salt to DB + $self->schema->resultset('Users')->create({ + username => $username, + email => $email, + password => $hash, + salt => $salt, + signup_date => time }) or die; + + $self->flash(message => 'User registered successfully!'); + $self->redirect_to('register')} + catch ($catchError) { + print $catchError; + $self->flash(error => 'Your registration info was correct, but a + server error prevented you from registering. This has been + logged so the administrator can fix it.'); + $self->redirect_to('register')}} + +1; \ No newline at end of file diff --git a/lib/CharmBoard/Crypt/Password.pm b/lib/CharmBoard/Crypt/Password.pm index 187567a..daa3b9a 100644 --- a/lib/CharmBoard/Crypt/Password.pm +++ b/lib/CharmBoard/Crypt/Password.pm @@ -1,14 +1,37 @@ package CharmBoard::Crypt::Password; +use utf8; use Authen::Passphrase::Argon2; use CharmBoard::Crypt::Seasoning; use Exporter qw(import); our @EXPORT = qw(passgen passchk); -# subroutine to generate password salt + hashed pw on pass creation -# outputs the salt and then the hashed pw, so when assigning vars -# from this sub's output, do it like this: -# `my ($salt, $hash) = passgen($password);` +=pod +=head1 NAME +CharmBoard::Crypt::Password - password processing module +=head1 SYNOPSIS +=begin perl +use CharmBoard::Crypt::Password; + +($salt, $hash) = passgen($plaintextPassword); +$passwordVerification = passchk($salt, $hash, $plaintextPassword) +=end perl +=head1 DESCRIPTION +CharmBoard::Crypt::Password processes passwords, either processing +new passwords for database storage, or checking passwords entered +when logging in to make sure they're correct. + +Currently the only available password hashing scheme is Argon2, but +this might be changed later on. +=cut + +=pod +=head2 passgen +passgen is the function for generating password salts and hashes to +be inserted into the database. It takes the plaintext password you +wish to hash as the only argument, and outputs the salt and +Argon2 hash string in hexadecimal form. +=cut sub passgen ($) { my $argon2 = Authen::Passphrase::Argon2->new( salt => seasoning(32), @@ -20,9 +43,17 @@ sub passgen ($) { return ($argon2->salt_hex, $argon2->hash_hex)}; -# subroutine to check inputted password against one in DB -# `$_[0]` is the salt, `$_[1]` is the hashed pass, and -# `$_[2]` is the inputted plaintext pepper:password to check +=pod +=head2 passchk +passchk is the function for checking plaintext passwords against the +hashed password + salt already stored in the database. It takes the +salt and Argon2 hash string in hex form plus the plaintext password +as inputs, and outputs a true/false value indicating whether or not +the input password matched. Intended for login authentication or +anywhere else where one may need to verify passwords (i.e. before +changing existing passwords, or for admins confirming they wish to +perform a risky or nonreversible operation.) +=cut sub passchk ($$$) { my $argon2 = Authen::Passphrase::Argon2->new( salt_hex => $_[0], diff --git a/lib/CharmBoard/Crypt/Seasoning.pm b/lib/CharmBoard/Crypt/Seasoning.pm index b2c7e2c..347dff2 100644 --- a/lib/CharmBoard/Crypt/Seasoning.pm +++ b/lib/CharmBoard/Crypt/Seasoning.pm @@ -1,4 +1,5 @@ package CharmBoard::Crypt::Seasoning; +use utf8; use Math::Random::Secure qw(irand); use Exporter qw(import); diff --git a/lib/CharmBoard/Schema.pm b/lib/CharmBoard/Schema.pm index 7725b4e..f39ba17 100644 --- a/lib/CharmBoard/Schema.pm +++ b/lib/CharmBoard/Schema.pm @@ -1,6 +1,8 @@ package CharmBoard::Schema; use base qw(DBIx::Class::Schema); -__PACKAGE__->load_namespaces(); +__PACKAGE__->load_namespaces( + result_namespace => 'Source', + resultset_namespace => 'Set'); 1; \ No newline at end of file diff --git a/lib/CharmBoard/Schema/Result/Categories.pm b/lib/CharmBoard/Schema/Source/Categories.pm similarity index 87% rename from lib/CharmBoard/Schema/Result/Categories.pm rename to lib/CharmBoard/Schema/Source/Categories.pm index 5e78132..fc4213d 100644 --- a/lib/CharmBoard/Schema/Result/Categories.pm +++ b/lib/CharmBoard/Schema/Source/Categories.pm @@ -1,4 +1,4 @@ -package CharmBoard::Schema::Result::Categories; +package CharmBoard::Schema::Source::Categories; use base qw(DBIx::Class::Core); __PACKAGE__->table('categories'); diff --git a/lib/CharmBoard/Schema/Result/Posts.pm b/lib/CharmBoard/Schema/Source/Posts.pm similarity index 74% rename from lib/CharmBoard/Schema/Result/Posts.pm rename to lib/CharmBoard/Schema/Source/Posts.pm index 85c8774..55a0398 100644 --- a/lib/CharmBoard/Schema/Result/Posts.pm +++ b/lib/CharmBoard/Schema/Source/Posts.pm @@ -1,22 +1,26 @@ -package CharmBoard::Schema::Result::Posts; +package CharmBoard::Schema::Source::Posts; use base qw(DBIx::Class::Core); __PACKAGE__->table('posts'); __PACKAGE__->add_columns( post_id => { data_type => 'integer', + is_foreign_key => 0, is_auto_increment => 1, is_nullable => 0, }, user_id => { data_type => 'integer', + is_foreign_key => 1, is_auto_increment => 0, is_nullable => 0, }, thread_id => { data_type => 'integer', + is_foreign_key => 1, is_auto_increment => 0, is_nullable => 0, }, post_date => { data_type => 'integer', + is_foreign_key => 0, is_auto_increment => 0, is_nullable => 0, }); @@ -24,11 +28,11 @@ __PACKAGE__->set_primary_key('post_id'); __PACKAGE__->belongs_to( user_id => - 'CharmBoard::Schema::Result::Users', + 'CharmBoard::Schema::Source::Users', 'user_id' ); __PACKAGE__->belongs_to( thread_id => - 'CharmBoard::Schema::Result::Threads', + 'CharmBoard::Schema::Source::Threads', 'thread_id' ); 1 \ No newline at end of file diff --git a/lib/CharmBoard/Schema/Result/Session.pm b/lib/CharmBoard/Schema/Source/Session.pm similarity index 90% rename from lib/CharmBoard/Schema/Result/Session.pm rename to lib/CharmBoard/Schema/Source/Session.pm index ef743ca..04378d6 100644 --- a/lib/CharmBoard/Schema/Result/Session.pm +++ b/lib/CharmBoard/Schema/Source/Session.pm @@ -1,4 +1,4 @@ -package CharmBoard::Schema::Result::Session; +package CharmBoard::Schema::Source::Session; use base qw(DBIx::Class::Core); __PACKAGE__->table('sessions'); @@ -28,7 +28,7 @@ __PACKAGE__->set_primary_key('session_key'); __PACKAGE__->belongs_to( user_id => - 'CharmBoard::Schema::Result::Users', + 'CharmBoard::Schema::Source::Users', 'user_id'); 1 \ No newline at end of file diff --git a/lib/CharmBoard/Schema/Result/Subforums.pm b/lib/CharmBoard/Schema/Source/Subforums.pm similarity index 84% rename from lib/CharmBoard/Schema/Result/Subforums.pm rename to lib/CharmBoard/Schema/Source/Subforums.pm index 7e112f1..8fd1949 100644 --- a/lib/CharmBoard/Schema/Result/Subforums.pm +++ b/lib/CharmBoard/Schema/Source/Subforums.pm @@ -1,4 +1,4 @@ -package CharmBoard::Schema::Result::Subforums; +package CharmBoard::Schema::Source::Subforums; use base qw(DBIx::Class::Core); __PACKAGE__->table('subforums'); @@ -9,6 +9,7 @@ __PACKAGE__->add_columns( is_nullable => 0, }, subf_cat => { data_type => 'integer', + is_foreign_key => 1, is_auto_increment => 0, is_nullable => 0, }, subf_name => { @@ -24,7 +25,7 @@ __PACKAGE__->set_primary_key('subf_id'); __PACKAGE__->belongs_to( subf_cat => - 'CharmBoard::Schema::Result::Categories', + 'CharmBoard::Schema::Source::Categories', {'foreign.cat_id' => 'self.subf_cat'}); 1 \ No newline at end of file diff --git a/lib/CharmBoard/Schema/Result/Threads.pm b/lib/CharmBoard/Schema/Source/Threads.pm similarity index 71% rename from lib/CharmBoard/Schema/Result/Threads.pm rename to lib/CharmBoard/Schema/Source/Threads.pm index 9368f22..452bd0b 100644 --- a/lib/CharmBoard/Schema/Result/Threads.pm +++ b/lib/CharmBoard/Schema/Source/Threads.pm @@ -1,4 +1,4 @@ -package CharmBoard::Schema::Result::Threads; +package CharmBoard::Schema::Source::Threads; use base qw(DBIx::Class::Core); __PACKAGE__->table('threads'); @@ -12,13 +12,16 @@ __PACKAGE__->add_columns( is_nullable => 0, }, thread_subf => { data_type => 'integer', + is_foreign_key => 1, is_nullable => 1, }); + # ! thread_subf should NOT be nullable once subforums + # ! are properly implemented __PACKAGE__->set_primary_key('thread_id'); __PACKAGE__->belongs_to( thread_subf => - 'CharmBoard::Schema::Result::Subforums', + 'CharmBoard::Schema::Source::Subforums', {'foreign.subf_id' => 'self.thread_subf'}); 1 \ No newline at end of file diff --git a/lib/CharmBoard/Schema/Result/Users.pm b/lib/CharmBoard/Schema/Source/Users.pm similarity index 94% rename from lib/CharmBoard/Schema/Result/Users.pm rename to lib/CharmBoard/Schema/Source/Users.pm index 24701aa..5f0ef2e 100644 --- a/lib/CharmBoard/Schema/Result/Users.pm +++ b/lib/CharmBoard/Schema/Source/Users.pm @@ -1,4 +1,5 @@ -package CharmBoard::Schema::Result::Users; +package CharmBoard::Schema::Source::Users; +use utf8; use base qw(DBIx::Class::Core); __PACKAGE__->table('users'); diff --git a/templates/index.html.ep b/templates/index.html.ep index 87cd4c7..cdc44af 100644 --- a/templates/index.html.ep +++ b/templates/index.html.ep @@ -1,4 +1,2 @@ -% layout 'default', title => 'CharmBoard'; -% my $hpm = "you are not logged in"; -% if ($self->session('is_auth')) {$hpm = "you're logged in!"}; -<%= $hpm %> \ No newline at end of file +% layout 'default', title => $self->boardName; +this is the index page \ No newline at end of file diff --git a/templates/layouts/_header.html.ep b/templates/layouts/_header.html.ep deleted file mode 100644 index 627fff5..0000000 --- a/templates/layouts/_header.html.ep +++ /dev/null @@ -1,2 +0,0 @@ -

CharmBoard

-login | register

\ No newline at end of file diff --git a/templates/layouts/default.html.ep b/templates/layouts/default.html.ep index 1697c90..e75ed15 100644 --- a/templates/layouts/default.html.ep +++ b/templates/layouts/default.html.ep @@ -5,8 +5,8 @@ <%= title %> - %= include 'layouts/_header' + %= include 'layouts/default/_header' <%= content %> - %= include 'layouts/_footer' + %= include 'layouts/default/_footer' \ No newline at end of file diff --git a/templates/layouts/_footer.html.ep b/templates/layouts/default/_footer.html.ep similarity index 100% rename from templates/layouts/_footer.html.ep rename to templates/layouts/default/_footer.html.ep diff --git a/templates/layouts/default/_header.html.ep b/templates/layouts/default/_header.html.ep new file mode 100644 index 0000000..79e5897 --- /dev/null +++ b/templates/layouts/default/_header.html.ep @@ -0,0 +1,14 @@ +<% +my $userControls; + +# TODO: once implemented, put username + profile link first +if ($self->session('is_auth') == 1) { + my $username = + $userControls = "logout"} +else { + $userControls = + "login | + register"}; +%> +

<%== $self->boardName %>

+<%== $userControls %>

\ No newline at end of file diff --git a/templates/login.html.ep b/templates/login.html.ep index 78b87c0..f40e11e 100644 --- a/templates/login.html.ep +++ b/templates/login.html.ep @@ -1,4 +1,4 @@ -% layout 'default', title => 'CharmBoard - Login'; +% layout 'default', title => $self->boardName . ' - Login'; % if ($error) {

<%= $error %>

%}; diff --git a/templates/register.html.ep b/templates/register.html.ep index 928c3d6..64b0d3e 100644 --- a/templates/register.html.ep +++ b/templates/register.html.ep @@ -1,4 +1,4 @@ -% layout 'default', title => 'CharmBoard - Registration'; +% layout 'default', title => $self->boardName . ' - Registration'; % if ($error) {

<%= $error %>

%};