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 @@