Set up + run perltidy, plus some manual format changes too

This commit is contained in:
ngoomie 2023-05-17 10:12:48 -06:00
parent fd585edc80
commit 51b2c54e9a
21 changed files with 399 additions and 267 deletions

6
.gitignore vendored
View File

@ -7,3 +7,9 @@ charmboard.conf
# Perl::Critic # Perl::Critic
perlcritic.log perlcritic.log
# Perl::Tidy
perltidy.log
*.tdy
*.pm.LOG
*.pl.LOG

42
.perltidyrc Normal file
View File

@ -0,0 +1,42 @@
-w
-log
-i=2
-l=70
-enc=utf8
-gcs
-ole=unix
-it=2
-ci=4
-xci
-cti=1
-nolq
-nola
-pt=2
-bt=1
-bbt=0
-tso
-nsts
-sfs
-nasc
-dsm
-aws
-dws
-fpva
-lop
-ibc
-nfs
-ce
-nbl
-olc
-dsm
-olq
-kis
-bbb
-kbl=1
-bar
-otr
-bbhb=3
-bbhbi=1
-wn
-vt=1
-nlal

View File

@ -16,48 +16,53 @@ sub startup {
$self->plugin('TagHelpers'); $self->plugin('TagHelpers');
# load configuration from config file # load configuration from config file
my $config = $self->plugin('Config' => my $config =
{file => 'charmboard.conf'}); $self->plugin('Config' => { file => 'charmboard.conf' });
# set this specific forum's name # set this specific forum's name
$self->helper(board_name => sub {$config->{board_name}}); $self->helper(board_name => sub { $config->{board_name} });
# load dev env only stuff, if applicable # load dev env only stuff, if applicable
if ($config->{environment} eq 'dev') { if ($config->{environment} eq 'dev') {
$self->plugin('Renderer::WithoutCache'); $self->plugin('Renderer::WithoutCache');
$self->renderer->cache->max_keys(0)}; $self->renderer->cache->max_keys(0)
}
# import Mojolicious secrets # import Mojolicious secrets
$self->secrets($config->{secrets}); $self->secrets($config->{secrets});
# import password pepper value # import password pepper value
$self->helper( $self->helper(pepper => sub { $config->{pass_crypt}->{pepper} });
pepper => sub {$config->{pass_crypt}->{pepper}});
## database setup ## database setup
# ? this could maybe be a given/when # ? this could maybe be a given/when
{ my ($_dsn, $_unicode); {
my ($_dsn, $_unicode);
if ($self->config->{database}->{type} ~~ 'sqlite') { if ($self->config->{database}->{type} ~~ 'sqlite') {
$_dsn = "dbi:SQLite:" . $config->{database}->{name}; $_dsn = "dbi:SQLite:" . $config->{database}->{name};
$_unicode = "sqlite_unicode"} $_unicode = "sqlite_unicode"
elsif ($self->config->{database}->{type} ~~ 'mariadb') { } elsif ($self->config->{database}->{type} ~~ 'mariadb') {
$_dsn = "dbi:mysql:" . $config->{database}->{name}; $_dsn = "dbi:mysql:" . $config->{database}->{name};
$_unicode = "mysql_enable_utf"} $_unicode = "mysql_enable_utf"
else {die "\nUnknown, unsupported, or empty database type } else {
die "\nUnknown, unsupported, or empty database type
in charmboard.conf. If you're sure you've set it to in charmboard.conf. If you're sure you've set it to
something supported, maybe double check your spelling? something supported, maybe double check your spelling?
\n\n\t \n\n\t
Valid options: 'sqlite', 'mariadb'"}; Valid options: 'sqlite', 'mariadb'"
}
our $schema = CharmBoard::Schema->connect( our $schema = CharmBoard::Schema->connect(
$_dsn, $_dsn,
$config->{database}->{user}, $config->{database}->{user},
$config->{database}->{pass}, $config->{database}->{pass},
{$_unicode => 1}); { $_unicode => 1 }
);
$self->helper(schema => sub {$schema})} $self->helper(schema => sub { $schema })
}
# router # router
my $r = $self->routes; my $r = $self->routes;
@ -65,34 +70,41 @@ sub startup {
# view subforum # view subforum
$r->get('/subforum/:id')->to( $r->get('/subforum/:id')->to(
controller => 'Controller::ViewSubf', controller => 'Controller::ViewSubf',
action => 'subf_view'); action => 'subf_view'
);
# controller routes # controller routes
## index page ## index page
$r->get('/')->to( $r->get('/')->to(
controller => 'Controller::Index', controller => 'Controller::Index',
action => 'index'); action => 'index'
);
## registration page ## registration page
$r->get('/register')->to( $r->get('/register')->to(
controller => 'Controller::Register', controller => 'Controller::Register',
action => 'register'); action => 'register'
);
$r->post('/register')->to( $r->post('/register')->to(
controller => 'Controller::Register', controller => 'Controller::Register',
action => 'register_do'); action => 'register_do'
);
## login page ## login page
$r->get('/login')->to( $r->get('/login')->to(
controller => 'Controller::Login', controller => 'Controller::Login',
action => 'login'); action => 'login'
);
$r->post('/login')->to( $r->post('/login')->to(
controller => 'Controller::Login', controller => 'Controller::Login',
action => 'login_do'); action => 'login_do'
);
## logout ## logout
$r->get('/logout')->to( $r->get('/logout')->to(
controller => 'Controller::Logout', controller => 'Controller::Logout',
action => 'logout_do') action => 'logout_do'
)
} }
1; 1;
@ -103,17 +115,17 @@ __END__
CharmBoard - revive the fun posting experience! CharmBoard - revive the fun posting experience!
=head1 NOTES =head1 NOTES
This documentation is intended for prospective code This documentation is intended for prospective code contributors. If
contributors. If you're looking to set CharmBoard up, you're looking to set CharmBoard up, look for the Markdown format
look for the Markdown format (.md) documentation instead. (.md) documentation instead.
CharmBoard uses a max line length of 60 chars and a tab CharmBoard uses a max line length of 70 chars and a tab size of two
size of two spaces. spaces.
=head1 DESCRIPTION =head1 DESCRIPTION
CharmBoard is forum software written in Perl with CharmBoard is forum software written in Perl with Mojolicious,
Mojolicious, intended to be a more fun alternative to the intended to be a more fun alternative to the bigger forum suites
bigger forum suites available today, inspired by older available today, inspired by older forum software like AcmlmBoard,
forum software like AcmlmBoard, while also being more while also being more modernized in terms of security practices than
modernized in terms of security practices than they are. they are.
=cut =cut

View File

@ -12,34 +12,35 @@ sub index {
my $self = shift; my $self = shift;
# fetch a list of all categories # fetch a list of all categories
my @all_cat = my @all_cat = $self->schema->resultset('Categories')->fetch_all;
$self->schema->resultset('Categories')->fetch_all;
# create a Tree::Simple object that will contain the list # create a Tree::Simple object that will contain the list
# of categories and the subforums that belong to them # of categories and the subforums that belong to them
my $tree = my $tree = Tree::Simple->new("subf_list", Tree::Simple->ROOT);
Tree::Simple->new("subf_list", Tree::Simple->ROOT);
my (@fetch_subf, $cat_branch); my (@fetch_subf, $cat_branch);
foreach my $iter_cat (@all_cat) { foreach my $iter_cat (@all_cat) {
# create branch of subf_list for the current category
$cat_branch = # create branch of subf_list for the current category
Tree::Simple->new($iter_cat, $tree); $cat_branch = Tree::Simple->new($iter_cat, $tree);
# fetch all subforums that belong to this category # fetch all subforums that belong to this category
@fetch_subf = @fetch_subf =
$self->schema->resultset('Subforums') $self->schema->resultset('Subforums')
->fetch_by_cat($iter_cat); ->fetch_by_cat($iter_cat);
# add each fetched subforum as children of the branch # add each fetched subforum as children of the branch
# for the current category # for the current category
foreach my $iter_subf (@fetch_subf) { foreach my $iter_subf (@fetch_subf) {
Tree::Simple->new($iter_subf, $cat_branch)}} Tree::Simple->new($iter_subf, $cat_branch)
}
}
$self->render( $self->render(
template => 'index', template => 'index',
category_tree => $tree)} category_tree => $tree
)
}
1; 1;
__END__ __END__

View File

@ -15,10 +15,12 @@ sub login {
$self->render( $self->render(
template => 'login', template => 'login',
error => $self->flash('error'), error => $self->flash('error'),
message => $self->flash('message'))}; message => $self->flash('message')
)
}
sub login_do { sub login_do {
my $self = shift; my $self = shift;
my $username = $self->param('username'); my $username = $self->param('username');
my $password = $self->pepper . ':' . $self->param('password'); my $password = $self->pepper . ':' . $self->param('password');
@ -28,24 +30,26 @@ sub login_do {
# 'our' so they work throughout the entire subroutine # 'our' so they work throughout the entire subroutine
our ($user_info, $pass_check, $user_id, $session_key); our ($user_info, $pass_check, $user_id, $session_key);
try { # check user credentials first # check user credentials first
try {
# check to see if user by entered username exists # check to see if user by entered username exists
$user_info = $self->schema->resultset('Users')->search( $user_info = $self->schema->resultset('Users')
{username => $username}); ->search({ username => $username });
$user_info or die; $user_info or die;
# now check password validity # now check password validity
$pass_check = passchk($user_info->get_column('salt')->first, $pass_check = passchk($user_info->get_column('salt')->first,
$user_info->get_column('password')->first, $password); $user_info->get_column('password')->first, $password);
$pass_check or die;} $pass_check or die;
catch ($catch_error) { # redirect to login page on fail } catch ($catch_error) { # redirect to login page on fail
print $catch_error; print $catch_error;
$self->flash(error => 'Username or password incorrect.'); $self->flash(error => 'Username or password incorrect.');
$self->redirect_to('login');} $self->redirect_to('login');
}
try { # now attempt to create session try { # now attempt to create session
# get user ID for session creation # get user ID for session creation
$user_id = $user_info->get_column('user_id')->first; $user_id = $user_info->get_column('user_id')->first;
# gen session key # gen session key
@ -57,23 +61,29 @@ sub login_do {
user_id => $user_id, user_id => $user_id,
session_expiry => time + 604800, session_expiry => time + 604800,
is_ip_bound => 0, is_ip_bound => 0,
bound_ip => undef }) or die; bound_ip => undef
})
or die;
# now create session cookie for user # now create session cookie for user
$self->session(is_auth => 1); $self->session(is_auth => 1 );
$self->session(user_id => $user_id); $self->session(user_id => $user_id );
$self->session(session_key => $session_key); $self->session(session_key => $session_key);
$self->session(expiration => 604800); $self->session(expiration => 604800 );
# redirect to index upon success # redirect to index upon success
$self->redirect_to('/')} $self->redirect_to('/')
catch ($catch_error) { # redirect to login page on fail } catch ($catch_error) { # redirect to login page on fail
print $catch_error; print $catch_error;
$self->flash(error => 'Your username and password were correct, $self->flash(
but a server error prevented you from logging in. This has been error => 'Your username and password were correct, but a server
logged so the administrator can fix it.'); error prevented you from logging in. This has been logged
$self->redirect_to('login')}} so the administrator can fix it.'
);
$self->redirect_to('login')
}
}
1; 1;

View File

@ -11,11 +11,16 @@ sub logout_do {
my $self = shift; my $self = shift;
# destroy entry for this session in the database # destroy entry for this session in the database
$self->schema->resultset('Session')->search({ $self->schema->resultset('Session')
session_key => $self->session('session_key')})->delete; ->search({ session_key => $self->session('session_key') })
->delete;
# now nuke the actual session cookie # now nuke the actual session cookie
$self->session(expires => 1); $self->session(expires => 1);
# redirect to index # redirect to index
$self->redirect_to('/')} $self->redirect_to('/')
}
1; 1;
__END__

View File

@ -14,7 +14,9 @@ sub register {
$self->render( $self->render(
template => 'register', template => 'register',
error => $self->flash('error'), error => $self->flash('error'),
message => $self->flash('message'))}; message => $self->flash('message')
)
}
# process submitted registration form # process submitted registration form
sub register_do { sub register_do {
@ -31,38 +33,41 @@ sub register_do {
# 'our' so they work throughout the entire subroutine # 'our' so they work throughout the entire subroutine
our ($userCheck, $emailCheck, $salt, $hash); our ($userCheck, $emailCheck, $salt, $hash);
try { # make sure registration info is valid # make sure registration info is valid
try {
# TODO: implement email validation here at some point # TODO: implement email validation here at some point
# check to make sure all required fields are filled # check to make sure all required fields are filled
($username, $email, $password, $confirmPassword) ($username, $email, $password, $confirmPassword)
or die "Please fill out all required fields."; or die "Please fill out all required fields.";
# check to make sure both passwords match # check to make sure both passwords match
# TODO: add check on frontend for this for people with JS enabled # TODO: add check on frontend for this for people with JS enabled
$password eq $confirmPassword $password eq $confirmPassword
or die "Passwords do not match"; or die "Passwords do not match";
# check to make sure username and/or email isn't already in use; # check to make sure username and/or email isn't already in use;
# if not, continue with registration # if not, continue with registration
## search for input username and email in database ## search for input username and email in database
$userCheck = $self->schema->resultset('Users')->search( $userCheck = $self->schema->resultset('Users')
{username => $username})->single; ->search({ username => $username })->single;
$emailCheck = $self->schema->resultset('Users')->search( $emailCheck = $self->schema->resultset('Users')
{email => $email})->single; ->search({ email => $email })->single;
($userCheck && $emailCheck) eq undef ($userCheck && $emailCheck) eq undef
or die "Username already in use.\nemail already in use."; or die "Username already in use.\nemail already in use.";
($userCheck) eq undef ($userCheck) eq undef
or die "Username already in use."; or die "Username already in use.";
($emailCheck) eq undef ($emailCheck) eq undef
or die "email already in use."} or die "email already in use."
catch ($catchError) { } catch ($catchError) {
$self->flash(error => $catchError); $self->flash(error => $catchError);
$self->redirect_to('register');} $self->redirect_to('register')
}
try { try {
$password = $self->pepper . ':' . $password; $password = $self->pepper . ':' . $password;
# return hashed result + salt # return hashed result + salt
($salt, $hash) = passgen($password) or die; ($salt, $hash) = passgen($password) or die;
@ -72,15 +77,22 @@ sub register_do {
email => $email, email => $email,
password => $hash, password => $hash,
salt => $salt, salt => $salt,
signup_date => time }) or die; signup_date => time
})
or die;
$self->flash(message => 'User registered successfully!'); $self->flash(message => 'User registered successfully!');
$self->redirect_to('register')} $self->redirect_to('register')
catch ($catchError) { } catch ($catchError) {
print $catchError; print $catchError;
$self->flash(error => 'Your registration info was correct, but a $self->flash(
server error prevented you from registering. This has been error =>
logged so the administrator can fix it.'); 'Your registration info was correct, but a server error
$self->redirect_to('register')}} prevented you from registering. This has been logged so the
administrator can fix it.'
);
$self->redirect_to('register')
}
}
1; 1;

View File

@ -12,21 +12,23 @@ sub subf_view {
my $subf_id = $self->param('id'); my $subf_id = $self->param('id');
my $subf_cat = my $subf_cat =
$self->schema->resultset('Subforums')->cat_from_id($subf_id); $self->schema->resultset('Subforums')->cat_from_id($subf_id);
my $cat_title = my $cat_title =
$self->schema->resultset('Categories') $self->schema->resultset('Categories')
->title_from_id($subf_cat); ->title_from_id($subf_cat);
my @thread_list = my @thread_list =
$self->schema->resultset('Threads')->fetch_by_subf($subf_id); $self->schema->resultset('Threads')->fetch_by_subf($subf_id);
$self->render( $self->render(
template => 'subf', template => 'subf',
subf_id => $subf_id, subf_id => $subf_id,
cat_title => $cat_title, cat_title => $cat_title,
subf_title => subf_title => $self->schema->resultset('Subforums')
$self->schema->resultset('Subforums')
->title_from_id($subf_id), ->title_from_id($subf_id),
thread_list => \@thread_list)} thread_list => \@thread_list
)
}
1; 1;
__END__

View File

@ -12,26 +12,30 @@ use Exporter qw(import);
our @EXPORT = qw(passgen passchk); our @EXPORT = qw(passgen passchk);
sub passgen { sub passgen {
my $argon2 = Authen::Passphrase::Argon2->new( my $_argon2 = Authen::Passphrase::Argon2->new(
salt => seasoning(32), salt => seasoning(32),
passphrase => $_[0], passphrase => $_[0],
cost => 17, cost => 17,
factor => '32M', factor => '32M',
parallelism => 1, parallelism => 1,
size => 32 ); size => 32
);
return ($argon2->salt_hex, $argon2->hash_hex)}; return ($_argon2->salt_hex, $_argon2->hash_hex)
}
sub passchk { sub passchk {
my $argon2 = Authen::Passphrase::Argon2->new( my $_argon2 = Authen::Passphrase::Argon2->new(
salt_hex => $_[0], salt_hex => $_[0],
hash_hex => $_[1], hash_hex => $_[1],
cost => 17, cost => 17,
factor => '32M', factor => '32M',
parallelism => 1, parallelism => 1,
size => 32 ); size => 32
);
return ($argon2->match($_[2]))} return ($_argon2->match($_[2]))
}
1; 1;

View File

@ -11,16 +11,20 @@ use Exporter qw(import);
our @EXPORT = qw(seasoning); our @EXPORT = qw(seasoning);
sub seasoning { sub seasoning {
my @spices = qw(0 1 2 3 4 5 6 7 8 9 a b c d e f g my @_spices = qw(0 1 2 3 4 5 6 7 8 9 a b c d e f g
h i j k l m n o p q r s t u v w x y z A B C D E F h i j k l m n o p q r s t u v w x y z A B C D E F
G H I J K L M N O P Q R S T U V W X Y Z ! @ $ % ^ G H I J K L M N O P Q R S T U V W X Y Z ! @ $ % ^
& * / ? . ; : \ [ ] - _ < > ` ~ + = £ ¥ ¢ §); & * / ? . ; : \ [ ] - _ < > ` ~ + = £ ¥ ¢ §);
my $blend; my $_blend;
while (length($blend) < $_[0]) { while (length($_blend) < $_[0]) {
# gen num to choose char for $blend
$blend = $blend . $spices[irand(@spices)]};
return ($blend); } # gen num to choose char for $blend
$_blend = $_blend . $_spices[ irand(@_spices) ]
}
return ($_blend)
}
1; 1;
__END__

View File

@ -8,8 +8,9 @@ use experimental qw(try smartmatch);
use base qw(DBIx::Class::Schema); use base qw(DBIx::Class::Schema);
__PACKAGE__->load_namespaces( __PACKAGE__->load_namespaces(
result_namespace => 'Source', result_namespace => 'Source',
resultset_namespace => 'Set'); resultset_namespace => 'Set'
);
1; 1;

View File

@ -10,26 +10,26 @@ use base 'DBIx::Class::ResultSet';
sub fetch_all { sub fetch_all {
my $_set = shift; my $_set = shift;
my $_fetch = my $_fetch = $_set->search({}, { order_by => 'cat_rank' });
$_set->search({},
{order_by => 'cat_rank'});
return($_fetch->get_column('cat_id')->all)} return ($_fetch->get_column('cat_id')->all)
}
sub title_from_id { sub title_from_id {
my $_set = shift; my $_set = shift;
return( return (
$_set->search({'cat_id' => $_[0]})-> $_set->search({ 'cat_id' => $_[0] })->get_column('cat_name')
get_column('cat_name')->first)} ->first)
}
1; 1;
__END__ __END__
=pod =pod
=head1 NAME =head1 NAME
CharmBoard::Schema::Set::Categories - DBIC ResultSet for CharmBoard::Schema::Set::Categories - DBIC ResultSet for the
the categories table categories table
=head1 SYNOPSIS =head1 SYNOPSIS
=head1 DESCRIPTION =head1 DESCRIPTION

View File

@ -10,26 +10,26 @@ use base 'DBIx::Class::ResultSet';
sub fetch_by_cat { sub fetch_by_cat {
my $_set = shift; my $_set = shift;
my $_fetch = my $_fetch = $_set->search({ 'subf_cat' => $_[0] },
$_set->search( { order_by => 'subf_rank' });
{'subf_cat' => $_[0] },
{order_by => 'subf_rank'});
return($_fetch->get_column('subf_id')->all)} return ($_fetch->get_column('subf_id')->all)
}
sub cat_from_id { sub cat_from_id {
my $_set = shift; my $_set = shift;
return( return (
$_set->search({'subf_id' => $_[0]})-> $_set->search({ 'subf_id' => $_[0] })->get_column('subf_cat')
get_column('subf_cat')->first)} ->first)
}
sub title_from_id { sub title_from_id {
my $_set = shift; my $_set = shift;
return( return ($_set->search({ 'subf_id' => $_[0] })
$_set->search({'subf_id' => $_[0]})-> ->get_column('subf_name')->first)
get_column('subf_name')->first)} }
1; 1;
__END__ __END__

View File

@ -11,16 +11,17 @@ sub fetch_by_subf {
my $_set = shift; my $_set = shift;
my $_fetch = my $_fetch =
$_set->search({'thread_subf' => $_[0]}); $_set->search({ 'thread_subf' => $_[0] });
return($_fetch->get_column('thread_id')->all)} return ($_fetch->get_column('thread_id')->all)
}
sub title_from_id { sub title_from_id {
my $_set = shift; my $_set = shift;
return( return ($_set->search({ 'thread_id' => $_[0] })
$_set->search({'thread_id' => $_[0]})-> ->get_column('thread_title')->first)
get_column('thread_title')->first)} }
1; 1;
__END__ __END__

View File

@ -9,16 +9,20 @@ use base qw(DBIx::Class::Core);
__PACKAGE__->table('categories'); __PACKAGE__->table('categories');
__PACKAGE__->add_columns( __PACKAGE__->add_columns(
cat_id => { cat_id =>
data_type => 'integer', { data_type => 'integer',
is_auto_increment => 1, is_auto_increment => 1,
is_nullable => 0, }, is_nullable => 0,
cat_rank => { },
data_type => 'integer', cat_rank =>
is_nullable => 0, }, { data_type => 'integer',
cat_name => { is_nullable => 0,
data_type => 'text', },
is_nullable => 0, }); cat_name =>
{ data_type => 'text',
is_nullable => 0,
}
);
__PACKAGE__->set_primary_key('cat_id'); __PACKAGE__->set_primary_key('cat_id');

View File

@ -9,32 +9,37 @@ use base qw(DBIx::Class::Core);
__PACKAGE__->table('posts'); __PACKAGE__->table('posts');
__PACKAGE__->add_columns( __PACKAGE__->add_columns(
post_id => { post_id =>
data_type => 'integer', { data_type => 'integer',
is_auto_increment => 1, is_auto_increment => 1,
is_nullable => 0, }, is_nullable => 0,
user_id => { },
data_type => 'integer', user_id =>
is_foreign_key => 1, { data_type => 'integer',
is_nullable => 0, }, is_foreign_key => 1,
thread_id => { is_nullable => 0,
data_type => 'integer', },
is_foreign_key => 1, thread_id =>
is_nullable => 0, }, { data_type => 'integer',
post_date => { is_foreign_key => 1,
data_type => 'integer', is_nullable => 0,
is_nullable => 0, }); },
post_date =>
{ data_type => 'integer',
is_nullable => 0,
}
);
__PACKAGE__->set_primary_key('post_id'); __PACKAGE__->set_primary_key('post_id');
__PACKAGE__->belongs_to( __PACKAGE__->belongs_to(
user_id => user_id => 'CharmBoard::Schema::Source::Users',
'CharmBoard::Schema::Source::Users', 'user_id'
'user_id' ); );
__PACKAGE__->belongs_to( __PACKAGE__->belongs_to(
thread_id => thread_id => 'CharmBoard::Schema::Source::Threads',
'CharmBoard::Schema::Source::Threads', 'thread_id'
'thread_id' ); );
1; 1;
__END__ __END__

View File

@ -9,28 +9,34 @@ use base qw(DBIx::Class::Core);
__PACKAGE__->table('sessions'); __PACKAGE__->table('sessions');
__PACKAGE__->add_columns( __PACKAGE__->add_columns(
session_key => { session_key =>
data_type => 'text', { data_type => 'text',
is_nullable => 0, }, is_nullable => 0,
user_id => { },
data_type => 'integer', user_id =>
is_nullable => 0, }, { data_type => 'integer',
session_expiry => { is_nullable => 0,
data_type => 'numeric', },
is_nullable => 0, }, session_expiry =>
is_ip_bound => { { data_type => 'numeric',
data_type => 'integer', is_nullable => 0,
is_nullable => 0, }, },
bound_ip => { is_ip_bound =>
data_type => 'text', { data_type => 'integer',
is_nullable => 1, }); is_nullable => 0,
},
bound_ip =>
{ data_type => 'text',
is_nullable => 1,
}
);
__PACKAGE__->set_primary_key('session_key'); __PACKAGE__->set_primary_key('session_key');
__PACKAGE__->belongs_to( __PACKAGE__->belongs_to(
user_id => user_id => 'CharmBoard::Schema::Source::Users',
'CharmBoard::Schema::Source::Users', 'user_id'
'user_id'); );
1; 1;
__END__ __END__

View File

@ -9,31 +9,37 @@ use base qw(DBIx::Class::Core);
__PACKAGE__->table('subforums'); __PACKAGE__->table('subforums');
__PACKAGE__->add_columns( __PACKAGE__->add_columns(
subf_id => { subf_id =>
data_type => 'integer', { data_type => 'integer',
is_auto_increment => 1, is_auto_increment => 1,
is_nullable => 0, }, is_nullable => 0,
subf_cat => { },
data_type => 'integer', subf_cat =>
is_foreign_key => 1, { data_type => 'integer',
is_nullable => 0, }, is_foreign_key => 1,
subf_rank => { is_nullable => 0,
data_type => 'integer', },
is_numeric => 1, subf_rank =>
is_nullable => 0, }, { data_type => 'integer',
subf_name => { is_numeric => 1,
data_type => 'text', is_nullable => 0,
is_nullable => 0, }, },
subf_desc => { subf_name =>
data_type => 'text', { data_type => 'text',
is_nullable => 1, }); is_nullable => 0,
},
subf_desc =>
{ data_type => 'text',
is_nullable => 1,
}
);
__PACKAGE__->set_primary_key('subf_id'); __PACKAGE__->set_primary_key('subf_id');
__PACKAGE__->belongs_to( __PACKAGE__->belongs_to(
subf_cat => subf_cat => 'CharmBoard::Schema::Source::Categories',
'CharmBoard::Schema::Source::Categories', { 'foreign.cat_id' => 'self.subf_cat' }
{'foreign.cat_id' => 'self.subf_cat'}); );
1; 1;
__END__ __END__

View File

@ -9,31 +9,37 @@ use base qw(DBIx::Class::Core);
__PACKAGE__->table('threads'); __PACKAGE__->table('threads');
__PACKAGE__->add_columns( __PACKAGE__->add_columns(
thread_id => { thread_id =>
data_type => 'integer', { data_type => 'integer',
is_auto_increment => 1, is_auto_increment => 1,
is_nullable => 0, }, is_nullable => 0,
thread_title => { },
data_type => 'text', thread_title =>
is_nullable => 0, }, { data_type => 'text',
thread_op => { is_nullable => 0,
data_type => 'integer', },
is_foreign_key => 1, thread_op =>
is_nullable => 0, }, { data_type => 'integer',
thread_subf => { is_foreign_key => 1,
data_type => 'integer', is_nullable => 0,
is_foreign_key => 1, },
is_nullable => 0, }); thread_subf =>
{ data_type => 'integer',
is_foreign_key => 1,
is_nullable => 0,
}
);
__PACKAGE__->set_primary_key('thread_id'); __PACKAGE__->set_primary_key('thread_id');
__PACKAGE__->belongs_to( __PACKAGE__->belongs_to(
thread_subf => thread_subf => 'CharmBoard::Schema::Source::Subforums',
'CharmBoard::Schema::Source::Subforums', { 'foreign.subf_id' => 'self.thread_subf' }
{'foreign.subf_id' => 'self.thread_subf'}); );
__PACKAGE__->belongs_to( __PACKAGE__->belongs_to(
thread_op => 'CharmBoard::Schema::Source::Posts', thread_op => 'CharmBoard::Schema::Source::Posts',
{'foreign.post_id' => 'self.thread_op'}); { 'foreign.post_id' => 'self.thread_op' }
);
1; 1;
__END__ __END__

View File

@ -9,27 +9,34 @@ use base qw(DBIx::Class::Core);
__PACKAGE__->table('users'); __PACKAGE__->table('users');
__PACKAGE__->add_columns( __PACKAGE__->add_columns(
user_id => { user_id =>
data_type => 'integer', { data_type => 'integer',
is_numeric => 1, is_numeric => 1,
is_nullable => 0, is_nullable => 0,
is_auto_increment => 1, }, is_auto_increment => 1,
username => { },
data_type => 'text', username =>
is_nullable => 0, }, { data_type => 'text',
email => { is_nullable => 0,
data_type => 'text', },
is_nullable => 0, }, email =>
password => { { data_type => 'text',
data_type => 'text', is_nullable => 0,
is_nullable => 0, }, },
salt => { password =>
data_type => 'text', { data_type => 'text',
is_nullable => 0, }, is_nullable => 0,
signup_date => { },
data_type => 'integer', salt =>
is_numeric => 1, { data_type => 'text',
is_nullable => 0, }); is_nullable => 0,
},
signup_date =>
{ data_type => 'integer',
is_numeric => 1,
is_nullable => 0,
}
);
__PACKAGE__->set_primary_key('user_id'); __PACKAGE__->set_primary_key('user_id');

View File

@ -13,5 +13,3 @@ use Mojolicious::Commands;
Mojolicious::Commands->start_app('CharmBoard'); Mojolicious::Commands->start_app('CharmBoard');
__END__ __END__