From c5785301cab7ce255a73a313c0d9b61eef210e3a Mon Sep 17 00:00:00 2001 From: ngoomie Date: Sun, 7 May 2023 00:04:15 -0600 Subject: [PATCH] Some prep for user sign in implementation + formatting changes global changes: - config now uses snake_case instead of camelCase for config entry names - closing brackets/braces never occur on their own line - there are almost never spaces inside brackets/braces before and after the actual content - I also removed a bunch of linebreaks I really shouldn't have because it just ended up worsening readability, so I'm going to put them back tomorrow lol `lib/CharmBoard.pm` : - removed PostgreSQL from the database driver detector, I just wanna stick with SQLite and MySQL initially since I'm only really familiar with those - detect dev environment (from conf file setting) and only shut caching off in that situation - removed the default layout config option `lib/CharmBoard/Crypt/Password.pm` - renamed subroutines from snake_case to whateverthisiscalled - changed what format `passgen` outputs salts and hashes in - changed size and factor for reasons I honestly don't remember at this point. I should probably recalibrate that properly tomorrow - added `passchk` subroutine for verifying of passwords on the login screen - nice and helpful comments `lib/CharmBoard/Crypt/Seasoning.pm` - this is what used to be `tools/pepper.pl`. it's not currently used for anything but it will be used for pepper generation during setup if CharmBoard ever gets to that point. also might use it for generating salts actually `lib/CharmBoard/Controller/Auth.pm` - realized I had the salt and hash variable assignments the wrong way 'round like an idiot, so I fixed that - added part of signup (password auth) - also lots of hopefully-helpful comments? `lib/CharmBoard/Schema/*.pm` - added more params for each column `lib/CharmBoard/Schema/Session.pm` - added `is_ip_bound` and `bound_ip` columns `database.sql` - as for stuff not mentioned in the schema module changes, I added `ON CONFLICT` behavior (it's all `ABORT`, which rolls back the entire transaction) i'm tired i'm spenfing too much time either reading about mojolicious/perl or actually programming in them (usually the former atm) i need to chillax and play some videogames --- .vscode/settings.json | 7 +- INSTALLING.md | 4 +- README.md | 16 ++-- charmboard.example.conf | 8 +- database.sql | 104 +++++++++++++++++---- lib/CharmBoard.pm | 81 ++++++---------- lib/CharmBoard/Controller/Auth.pm | 83 +++++++++------- lib/CharmBoard/Controller/Main.pm | 3 +- lib/CharmBoard/Crypt/Password.pm | 35 +++++-- lib/CharmBoard/Crypt/Seasoning.pm | 20 ++++ lib/CharmBoard/Schema/Result/Categories.pm | 6 +- lib/CharmBoard/Schema/Result/Posts.pm | 22 ++--- lib/CharmBoard/Schema/Result/Session.pm | 33 ++++--- lib/CharmBoard/Schema/Result/Subforums.pm | 18 ++-- lib/CharmBoard/Schema/Result/Threads.pm | 12 +-- lib/CharmBoard/Schema/Result/Users.pm | 23 ++--- tools/pepper.pl | 25 ----- 17 files changed, 285 insertions(+), 215 deletions(-) create mode 100644 lib/CharmBoard/Crypt/Seasoning.pm delete mode 100755 tools/pepper.pl diff --git a/.vscode/settings.json b/.vscode/settings.json index a4d38eb..0b963d1 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -8,8 +8,13 @@ "Authen", "CharmBoard", "Facepunch", + "passchk", + "passgen", "pgsql", "resultset", - "signup" + "signup", + "subf", + "subforum", + "subforums" ] } \ No newline at end of file diff --git a/INSTALLING.md b/INSTALLING.md index 32d5642..6bd9550 100644 --- a/INSTALLING.md +++ b/INSTALLING.md @@ -4,13 +4,13 @@ Please keep in mind that CharmBoard is alpha software, and as such should not be ## Preparation -### Database types +### Selecting a database type CharmBoard supports two different types of databases. Below is a table listing off each type, as well as an explanation of the differences for people who are unsure which to pick. | Name | config value | DBD package | Information | |-|-|-|-| -| SQLite | `sqlite` | `DBD:SQLite` | Good for small installs (private forum with one friend group, etc.)
Easy to set up as the database is contained in a standalone file. | +| SQLite | `sqlite` | `DBD:SQLite` | Good for small installs (i.e. a private forum with one friend group, etc.)
Easy to set up as the database is contained in a standalone file. | | MySQL | `mysql` | `DBD:mysql` | Has better performance on larger databases than SQLite does.
Harder to set up than SQLite as it requires the separate database server software to be set up alongside CharmBoard. | ### Installing dependencies diff --git a/README.md b/README.md index 4e0f6b7..e79b4d4 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,17 @@ # CharmBoard -CharmBoard is forum software written in Perl, inspired by AcmlmBoard/its derivatives, the original Facepunch forums, and Knockout.chat. It's intended to be a more "fun" alternative to the bigger forum software suites available today. +CharmBoard is forum software written in Perl, inspired by AcmlmBoard/its derivatives, the original Facepunch forums, and Knockout.chat. It's intended to be a more "fun" alternative to the bigger forum software suites available today. Though largely, it's just intended as a sort of pet project of mine for now and a way to learn Perl + Mojolicious, and some other modules I've been wanting to learn. ## Requirements -- Perl 5 (TODO: specific version reqs) - - `Mojolicious` ([website](https://www.mojolicious.org/), [metacpan](https://metacpan.org/pod/Mojolicious)) - - `DBI` - - `DBIx::Class` - - one of two `DBD` database drivers — see `INSTALLING.md` for detailed information - - `Authen::Passphrase::Argon2` +- Perl5 v5.20.0 or higher +- `Mojolicious` ([website](https://www.mojolicious.org/), [metacpan](https://metacpan.org/pod/Mojolicious)) + - `Mojolicious::Plugin::Renderer::WithoutCache` — only needed in dev environment +- `DBI` + - `DBIx::Class` + - one of two `DBD` database drivers — see `INSTALLING.md` for detailed information +- `Authen::Passphrase::Argon2` +- `Math::Random::Secure` ## Installation diff --git a/charmboard.example.conf b/charmboard.example.conf index 4c7ed0f..c827b77 100644 --- a/charmboard.example.conf +++ b/charmboard.example.conf @@ -1,16 +1,18 @@ { - boardName => '', # this doesn't do anything yet + board_name => '', # this doesn't do anything yet database => { - type => '', # 'sqlite', 'mysql', or 'pgsql' + type => '', # 'sqlite' or 'mysql' name => '', user => '', pass => '' }, - passCrypt => { + pass_crypt => { pepper => '' # generate this with `tools/pepper.pl` for now }, + environment => '', # only use 'dev' for now + secrets => [''] }; \ No newline at end of file diff --git a/database.sql b/database.sql index 6209daa..0579130 100644 --- a/database.sql +++ b/database.sql @@ -1,5 +1,5 @@ -- --- File generated with SQLiteStudio v3.4.4 on Sat. May 6 00:01:26 2023 +-- File generated with SQLiteStudio v3.4.4 on Sun. May 7 00:02:05 2023 -- -- Text encoding used: UTF-8 -- @@ -8,40 +8,104 @@ BEGIN TRANSACTION; -- Table: categories DROP TABLE IF EXISTS categories; -CREATE TABLE IF NOT EXISTS categories (cat_id INTEGER NOT NULL UNIQUE, cat_name TEXT, PRIMARY KEY (cat_id AUTOINCREMENT)); + +CREATE TABLE IF NOT EXISTS categories ( + cat_id INTEGER NOT NULL ON CONFLICT ROLLBACK + UNIQUE ON CONFLICT ROLLBACK, + cat_name TEXT, + PRIMARY KEY ( + cat_id AUTOINCREMENT + ) +); + -- Table: posts DROP TABLE IF EXISTS posts; -CREATE TABLE IF NOT EXISTS "posts" ( - "post_id" INTEGER NOT NULL UNIQUE, - "user_id" INTEGER NOT NULL, - "thread_id" INTEGER NOT NULL, - "post_date" INTEGER NOT NULL, - PRIMARY KEY("post_id" AUTOINCREMENT), - FOREIGN KEY("user_id") REFERENCES "users"("user_id"), - FOREIGN KEY("thread_id") REFERENCES "threads"("thread_id") + +CREATE TABLE IF NOT EXISTS posts ( + post_id INTEGER NOT NULL ON CONFLICT ROLLBACK + UNIQUE ON CONFLICT ROLLBACK, + user_id INTEGER NOT NULL ON CONFLICT ROLLBACK, + thread_id INTEGER NOT NULL ON CONFLICT ROLLBACK, + post_date INTEGER NOT NULL ON CONFLICT ROLLBACK, + PRIMARY KEY ( + post_id AUTOINCREMENT + ), + FOREIGN KEY ( + user_id + ) + REFERENCES users (user_id), + FOREIGN KEY ( + thread_id + ) + REFERENCES threads (thread_id) ); --- Table: session -DROP TABLE IF EXISTS session; -CREATE TABLE IF NOT EXISTS "session" ( - "user_id" INTEGER NOT NULL UNIQUE, - "session_id" TEXT NOT NULL, - "session_expiry" INTEGER, - PRIMARY KEY("user_id") + +-- Table: sessions +DROP TABLE IF EXISTS sessions; + +CREATE TABLE IF NOT EXISTS sessions ( + user_id INTEGER PRIMARY KEY + REFERENCES users (user_id) + UNIQUE + NOT NULL, + session_key TEXT NOT NULL + UNIQUE, + session_expiry NUMERIC NOT NULL, + is_ip_bound INTEGER (1, 1) NOT NULL + DEFAULT (0), + bound_ip TEXT ); + -- Table: subforums DROP TABLE IF EXISTS subforums; -CREATE TABLE IF NOT EXISTS subforums (subf_id INTEGER PRIMARY KEY UNIQUE NOT NULL, subf_cat INTEGER REFERENCES categories (cat_id) UNIQUE NOT NULL, subf_name TEXT NOT NULL, subf_desc); + +CREATE TABLE IF NOT EXISTS subforums ( + subf_id INTEGER PRIMARY KEY + UNIQUE ON CONFLICT ROLLBACK + NOT NULL ON CONFLICT ROLLBACK, + subf_cat INTEGER REFERENCES categories (cat_id) + UNIQUE ON CONFLICT ROLLBACK + NOT NULL ON CONFLICT ROLLBACK, + subf_name TEXT NOT NULL ON CONFLICT ROLLBACK, + subf_desc +); + -- Table: threads DROP TABLE IF EXISTS threads; -CREATE TABLE IF NOT EXISTS threads (thread_id INTEGER NOT NULL, thread_title TEXT NOT NULL, thread_subf INTEGER REFERENCES categories (cat_id), PRIMARY KEY (thread_id AUTOINCREMENT)); + +CREATE TABLE IF NOT EXISTS threads ( + thread_id INTEGER NOT NULL ON CONFLICT ROLLBACK, + thread_title TEXT NOT NULL ON CONFLICT ROLLBACK, + thread_subf INTEGER REFERENCES categories (cat_id), + PRIMARY KEY ( + thread_id AUTOINCREMENT + ) +); + -- Table: users DROP TABLE IF EXISTS users; -CREATE TABLE IF NOT EXISTS users (user_id INTEGER NOT NULL UNIQUE, username TEXT NOT NULL UNIQUE ON CONFLICT ABORT, email TEXT UNIQUE NOT NULL, password INTEGER NOT NULL, salt TEXT NOT NULL, signup_date INTEGER NOT NULL, PRIMARY KEY (user_id AUTOINCREMENT) ON CONFLICT FAIL); + +CREATE TABLE IF NOT EXISTS users ( + user_id INTEGER NOT NULL ON CONFLICT ROLLBACK + UNIQUE ON CONFLICT ROLLBACK, + username TEXT NOT NULL ON CONFLICT ROLLBACK + UNIQUE ON CONFLICT ROLLBACK, + email TEXT UNIQUE ON CONFLICT ROLLBACK + NOT NULL ON CONFLICT ROLLBACK, + password TEXT NOT NULL ON CONFLICT ROLLBACK, + salt TEXT NOT NULL ON CONFLICT ROLLBACK, + signup_date REAL NOT NULL, + PRIMARY KEY ( + user_id AUTOINCREMENT + ) + ON CONFLICT ABORT +); + COMMIT TRANSACTION; PRAGMA foreign_keys = on; diff --git a/lib/CharmBoard.pm b/lib/CharmBoard.pm index 2ce2e7f..733f225 100644 --- a/lib/CharmBoard.pm +++ b/lib/CharmBoard.pm @@ -3,84 +3,65 @@ use experimental 'smartmatch'; use Mojo::Base 'Mojolicious', -signatures; use CharmBoard::Schema; -# This method will run once at server start +# this method will run once at server start sub startup ($app) { - - $app = shift; - + # load plugins that require no additional conf $app->plugin('TagHelpers'); - $app->plugin('Renderer::WithoutCache'); # for dev env only - $app->renderer->cache->max_keys(0); # for dev env only + # load configuration from config file + my $config = $app->plugin('Config' => {file => 'charmboard.conf'}); - $app->defaults(layout => 'default'); - - # Load configuration from config file - my $config = $app->plugin('Config' => { - file => 'charmboard.conf' - }); + # load dev env only stuff, if applicable + if ( $config->{environment} eq 'dev' ) { + $app->plugin('Renderer::WithoutCache'); + $app->renderer->cache->max_keys(0)}; - # Configure the application - ## Import Mojolicious secrets (cookie encryption) + # import Mojolicious secrets $app->secrets($config->{secrets}); - ## Import password pepper value - my $pepper = $config->{passCrypt}->{pepper}; - $app->helper( pepper => sub { $pepper } ); - ## Database setup - my ($dsn, $dbUnicode); + # import password pepper value + $app->helper(pepper => sub {$config->{pass_crypt}->{pepper}}); + + ## database setup + my ($dsn, $dbUnicode); if ($app->config->{database}->{type} ~~ 'sqlite') { $dsn = "dbi:SQLite:" . $config->{database}->{name}; - $dbUnicode = "sqlite_unicode"; - } elsif ($app->config->{database}->{type} ~~ 'mysql') { + $dbUnicode = "sqlite_unicode"} + elsif ($app->config->{database}->{type} ~~ 'mysql') { $dsn = "dbi:mysql:" . $config->{database}->{name}; - $dbUnicode = "mysql_enable_utf"; - } elsif ($app->config->{database}->{type} ~~ 'pgsql') { - $dsn = "dbi:Pg:" . $config->{database}->{name}; - $dbUnicode = "pg_enable_utf8"; - } else { die "\nUnknown, unsupported, or empty database type in charmboard.conf. + $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 - Valid options: 'sqlite', 'mysql'" - }; - + Valid options: 'sqlite', 'mysql'"}; my $schema = CharmBoard::Schema->connect( $dsn, $config->{database}->{user}, $config->{database}->{pass}, - { - $dbUnicode => 1 - } - ); + {$dbUnicode => 1}); + $app->helper(schema => sub {$schema}); - $app->helper( schema => sub { $schema } ); - - # Router + # router my $r = $app->routes; - # Controller routes - ## Index page + # controller routes + ## index page $r->get('/')->to( controller => 'Controller::Main', - action => 'index' - ); - ## Registration page + action => 'index'); + ## registration page $r->get('/register')->to( controller => 'Controller::Auth', - action => 'register' - ); + action => 'register'); $r->post('/register')->to( controller => 'Controller::Auth', - action => 'registration_do' - ); - ## Login page + action => 'register_do'); + ## login page $r->get('/login')->to( controller => 'Controller::Auth', - action => 'login' - ); + action => 'login'); $r->post('/login')->to( controller => 'Controller::Auth', - action => 'login_do' - ) + action => 'login_do'); } 1; diff --git a/lib/CharmBoard/Controller/Auth.pm b/lib/CharmBoard/Controller/Auth.pm index db24b0f..cd00ac1 100644 --- a/lib/CharmBoard/Controller/Auth.pm +++ b/lib/CharmBoard/Controller/Auth.pm @@ -1,6 +1,8 @@ package CharmBoard::Controller::Auth; use Mojo::Base 'Mojolicious::Controller', -signatures; use CharmBoard::Crypt::Password; +use CharmBoard::Crypt::Seasoning; +use Time::HiRes qw(time); # initial registration page sub register ($app) { @@ -11,63 +13,80 @@ sub register ($app) { )}; # process submitted registration form -sub registration_do ($app) { +# TODO: implement email validation here at some point +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'); # check to make sure all required fields are filled - if ( ! $username || ! $password || ! $confirmPassword ) { - $app->flash( error => 'All fields required.' ); - $app->redirect_to('register'); - }; + if (! $username || ! $password || ! $confirmPassword) { + $app->flash(error => 'All fields required.'); + $app->redirect_to('register')}; # check to make sure both passwords match # TODO: add check on frontend for this for people with JS enabled - if ( $confirmPassword ne $password ) { - $app->flash( error => 'Passwords do not match.' ); - $app->redirect_to('register'); - }; + if ($confirmPassword ne $password) { + $app->flash(error => 'Passwords do not match.'); + $app->redirect_to('register')}; # 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 my $userCheck = $app->schema->resultset('Users')->search({username => $username})->single; my $emailCheck = $app->schema->resultset('Users')->search({email => $email})->single; - if ( $userCheck || $emailCheck ) { - if ( $userCheck && $emailCheck ) { - # notify user that username and email are both already being used - $app->flash( error => 'Username and email already in use.' ); - $app->redirect_to('register'); - } elsif ( $userCheck ) { - # notify user that only username is already in use - $app->flash( error => 'Username is already in use.' ); - $app->redirect_to('register'); - } elsif ( $emailCheck ) { - # notify user that only email is already in use - $app->flash( error => 'email is already in use.' ); - $app->redirect_to('register'); - } - } else { + + if ($userCheck || $emailCheck) { + if ($userCheck && $emailCheck) { # notify user that username and email are both already being used + $app->flash(error => 'Username and email already in use.'); + $app->redirect_to('register')} + elsif ($userCheck) { # notify user that only username is already in use + $app->flash(error => 'Username is already in use.'); + $app->redirect_to('register')} + elsif ($emailCheck) { # notify user that only email is already in use + $app->flash(error => 'email is already in use.'); + $app->redirect_to('register')}} + else { # TODO: add more error handling here, in case SQL transact fails + # append pepper to pass before hashing $password = $app->pepper . ':' . $password; - my ($hash, $salt) = pass_gen($password); + # return hashed result + salt + my ($salt, $hash) = passgen($password); + # add user info and pw/salt to DB $app->schema->resultset('Users')->create({ username => $username, email => $email, password => $hash, salt => $salt, - signup_date => time - }); - $app->flash( message => 'User registered successfully!' ); - $app->redirect_to('register'); - }}; + signup_date => time }); + $app->flash(message => 'User registered successfully!'); + $app->redirect_to('register')}}; sub login ($app) { $app->render( template => 'login', error => $app->flash('error'), - message => $app->flash('message') - ); + message => $app->flash('message'))}; + +sub login_do ($app) { + my $username = $app->param('username'); + my $password = $app->param('password'); + $password = $app->pepper . ':' . $password; + my $userInfoCheck = $app->schema->resultset('Users')->search({username => $username}); + if ($userInfoCheck) { + my $savedSalt = $userInfoCheck->get_column('salt')->first; + my $savedHash = $userInfoCheck->get_column('password')->first; + my $passCheckStatus = passchk($savedSalt, $savedHash, $password); + if ($passCheckStatus) { + $app->flash(message => 'Password correct, but auth isn\'t implemented yet'); + $app->redirect_to('login') + } else { + $app->flash(error => 'Password incorrect'); + $app->redirect_to('login')}} + else { + $app->flash(error => 'User ' . $username . ' does not exist.'); + $app->redirect_to('login')}; + } 1; \ No newline at end of file diff --git a/lib/CharmBoard/Controller/Main.pm b/lib/CharmBoard/Controller/Main.pm index 5234ee7..cc3cc65 100644 --- a/lib/CharmBoard/Controller/Main.pm +++ b/lib/CharmBoard/Controller/Main.pm @@ -2,7 +2,6 @@ package CharmBoard::Controller::Main; use Mojo::Base 'Mojolicious::Controller', -signatures; sub index ($app) { - $app->render(template => 'index'); -} + $app->render(template => 'index')} 1; \ No newline at end of file diff --git a/lib/CharmBoard/Crypt/Password.pm b/lib/CharmBoard/Crypt/Password.pm index 5c2934a..72300b8 100644 --- a/lib/CharmBoard/Crypt/Password.pm +++ b/lib/CharmBoard/Crypt/Password.pm @@ -2,20 +2,35 @@ package CharmBoard::Crypt::Password; use Authen::Passphrase::Argon2; use Exporter qw(import); +our @EXPORT = qw(passgen passchk); -our @EXPORT = qw(pass_gen); - -sub pass_gen ($) { +# 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);` +sub passgen ($) { my $argon2 = Authen::Passphrase::Argon2->new( salt_random => 1, - passphrase => $_[0], - cost => 3, - factor => '16M', + passphrase => $_[0], + cost => 3, + factor => '32M', parallelism => 1, - size => 32 - ); + size => 16 ); - return ($argon2->salt_hex, $argon2->as_hex); -} + return ($argon2->salt, $argon2->as_crypt)}; + +# 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 +sub passchk ($$$) { + my $argon2 = Authen::Passphrase::Argon2->new( + salt => $_[0], + hash => $_[1], + cost => 3, + factor => '32M', + parallelism => 1, + size => 16 ); + + return ($argon2->match($_[2]))} 1; \ No newline at end of file diff --git a/lib/CharmBoard/Crypt/Seasoning.pm b/lib/CharmBoard/Crypt/Seasoning.pm new file mode 100644 index 0000000..b2c7e2c --- /dev/null +++ b/lib/CharmBoard/Crypt/Seasoning.pm @@ -0,0 +1,20 @@ +package CharmBoard::Crypt::Seasoning; +use Math::Random::Secure qw(irand); + +use Exporter qw(import); +our @EXPORT = qw(seasoning); + +sub seasoning ($) { + 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 + G H I J K L M N O P Q R S T U V W X Y Z ! @ $ % ^ + & * / ? . ; : \ [ ] - _ < > ` ~ + = £ ¥ ¢); + + my $blend; + while (length($blend) < $_[0]) { + # gen num to choose char for $blend + $blend = $blend . $spices[irand(@spices)]}; + + return ($blend); } + +1; \ No newline at end of file diff --git a/lib/CharmBoard/Schema/Result/Categories.pm b/lib/CharmBoard/Schema/Result/Categories.pm index 894e43f..e39134a 100644 --- a/lib/CharmBoard/Schema/Result/Categories.pm +++ b/lib/CharmBoard/Schema/Result/Categories.pm @@ -6,12 +6,10 @@ __PACKAGE__->add_columns( cat_id => { data_type => 'integer', is_auto_increment => 1, - is_nullable => 0, - }, + is_nullable => 0, }, cat_name => { data_type => 'text', - is_nullable => 0, - }); + is_nullable => 0, }); __PACKAGE__->set_primary_key('cat_id'); 1 \ No newline at end of file diff --git a/lib/CharmBoard/Schema/Result/Posts.pm b/lib/CharmBoard/Schema/Result/Posts.pm index 47a6143..e74a958 100644 --- a/lib/CharmBoard/Schema/Result/Posts.pm +++ b/lib/CharmBoard/Schema/Result/Posts.pm @@ -6,33 +6,27 @@ __PACKAGE__->add_columns( post_id => { data_type => 'integer', is_auto_increment => 1, - is_nullable => 0, - }, + is_nullable => 0, }, user_id => { data_type => 'integer', - is_auto_increment => 1, - is_nullable => 0, - }, + is_auto_increment => 0, + is_nullable => 0, }, thread_id => { data_type => 'integer', is_auto_increment => 1, - is_nullable => 0, - }, + is_nullable => 0, }, post_date => { data_type => 'integer', - is_auto_increment => 1, - is_nullable => 0, - }); + is_auto_increment => 0, + is_nullable => 0, }); __PACKAGE__->set_primary_key('post_id'); __PACKAGE__->belongs_to( user_id => 'CharmBoard::Schema::Result::Users', - 'user_id' -); + 'user_id' ); __PACKAGE__->belongs_to( thread_id => 'CharmBoard::Schema::Result::Threads', - 'thread_id' -); + 'thread_id' ); 1 \ No newline at end of file diff --git a/lib/CharmBoard/Schema/Result/Session.pm b/lib/CharmBoard/Schema/Result/Session.pm index 77adedb..8361c6e 100644 --- a/lib/CharmBoard/Schema/Result/Session.pm +++ b/lib/CharmBoard/Schema/Result/Session.pm @@ -1,25 +1,32 @@ package CharmBoard::Schema::Result::Session; use base qw(DBIx::Class::Core); -__PACKAGE__->table('session'); +__PACKAGE__->table('sessions'); __PACKAGE__->add_columns( user_id => { - data_type => 'integer', - is_nullable => 0, - }, - session_id => { - data_type => 'text', - is_nullable => 0, - }, + data_type => 'integer', + is_auto_increment => 0, + is_nullable => 0, }, + session_key => { + data_type => 'text', + is_auto_increment => 0, + is_nullable => 0, }, session_expiry => { - data_type => 'integer', - is_nullable => 0, - }); + data_type => 'numeric', + is_auto_increment => 0, + is_nullable => 0, }, + is_ip_bound => { + data_type => 'integer', + is_auto_increment => 0, + is_nullable => 0, }, + bound_ip => { + data_type => 'text', + is_auto_increment => 0, + is_nullable => 1, }); __PACKAGE__->set_primary_key('user_id'); __PACKAGE__->belongs_to( user_id => 'CharmBoard::Schema::Result::Users', - 'user_id' -); + 'user_id'); 1 \ No newline at end of file diff --git a/lib/CharmBoard/Schema/Result/Subforums.pm b/lib/CharmBoard/Schema/Result/Subforums.pm index 182f4f1..167e4c4 100644 --- a/lib/CharmBoard/Schema/Result/Subforums.pm +++ b/lib/CharmBoard/Schema/Result/Subforums.pm @@ -6,25 +6,23 @@ __PACKAGE__->add_columns( subf_id => { data_type => 'integer', is_auto_increment => 1, - is_nullable => 0, - }, + is_nullable => 0, }, subf_cat => { data_type => 'integer', - is_nullable => 0, - }, + is_auto_increment => 0, + is_nullable => 0, }, subf_name => { data_type => 'text', - is_nullable => 0, - }, + is_auto_increment => 0, + is_nullable => 0, }, subf_desc => { data_type => 'text', - is_nullable => 1, - }); + is_auto_increment => 0, + is_nullable => 1, }); __PACKAGE__->set_primary_key('subf_id'); __PACKAGE__->belongs_to( subf_cat => 'CharmBoard::Schema::Result::Categories', - {'foreign.cat_id' => 'self.subf_cat'} -); + {'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/Result/Threads.pm index 9a577a3..8162eca 100644 --- a/lib/CharmBoard/Schema/Result/Threads.pm +++ b/lib/CharmBoard/Schema/Result/Threads.pm @@ -6,21 +6,17 @@ __PACKAGE__->add_columns( thread_id => { data_type => 'integer', is_auto_increment => 1, - is_nullable => 0, - }, + is_nullable => 0, }, thread_title => { data_type => 'text', - is_nullable => 0, - }, + is_nullable => 0, }, thread_subf => { data_type => 'integer', - is_nullable => 1, - }); + is_nullable => 1, }); __PACKAGE__->set_primary_key('thread_id'); __PACKAGE__->belongs_to( thread_subf => 'CharmBoard::Schema::Result::Subforums', - {'foreign.subf_id' => 'self.thread_subf'} -); + {'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/Result/Users.pm index 35eb272..09c262a 100644 --- a/lib/CharmBoard/Schema/Result/Users.pm +++ b/lib/CharmBoard/Schema/Result/Users.pm @@ -7,28 +7,23 @@ __PACKAGE__->add_columns( data_type => 'integer', is_numeric => 1, is_nullable => 0, - is_auto_increment => 1 - }, + is_auto_increment => 1, }, username => { data_type => 'text', - is_nullable => 0 - }, - email => { - data_type => 'text' - }, + is_nullable => 0, }, + email => { + data_type => 'text', + is_nullable => 0, }, password => { data_type => 'text', - is_nullable => 0 - }, + is_nullable => 0, }, salt => { data_type => 'text', - is_nullable => 0 - }, + is_nullable => 0, }, signup_date => { - data_type => 'integer', + data_type => 'real', is_numeric => 1, - is_nullable => 0 - }); + is_nullable => 0, }); __PACKAGE__->set_primary_key('user_id'); 1 \ No newline at end of file diff --git a/tools/pepper.pl b/tools/pepper.pl deleted file mode 100755 index cf99325..0000000 --- a/tools/pepper.pl +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env perl -use warnings; -use strict; -use Math::Random::Secure qw( irand ); - -my @chars = 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 G H I J K L M N - O P Q R S T U V W X - Y Z ! @ $ % ^ & * / - ? . ; : \ [ ] - _ ); - -my $pepper = ''; -while ( length($pepper) < 25 ) { - # gen and discard numbers to flush out dupe chance - irand(255); irand(255); irand(255); irand(255); - irand(255); irand(255); irand(255); irand(255); - # gen num for pepper - $pepper = $pepper . $chars[irand(@chars)]; -} - -print("Your pepper value is:\n"); -print($pepper); \ No newline at end of file