parent
a107f69afc
commit
dcde57aa5f
8 changed files with 789 additions and 0 deletions
@ -0,0 +1,18 @@ |
|||||||
|
#!/usr/bin/env bash |
||||||
|
|
||||||
|
CLASS_NAME="MJB::DB" |
||||||
|
|
||||||
|
# Generate a random 8 character name for the docker container that holds the PSQL |
||||||
|
# database. |
||||||
|
PSQL_NAME=$(cat /dev/urandom | LC_ALL=C tr -dc 'a-zA-Z' | fold -w 8 | head -n 1) |
||||||
|
|
||||||
|
# Launch a PSQL Instance |
||||||
|
PSQL_DOCKER=`docker run --rm --name $PSQL_NAME -e POSTGRES_PASSWORD=dbic -e POSTGRES_USER=dbic -e POSTGRES_DB=dbic -d \ |
||||||
|
--mount type=bind,src=$PWD/etc/schema.sql,dst=/docker-entrypoint-initdb.d/schema.sql postgres:11` |
||||||
|
|
||||||
|
docker run --rm --link $PSQL_NAME:psqldb --mount type=bind,src=$PWD,dst=/app symkat/schema_builder /bin/build-schema $CLASS_NAME |
||||||
|
|
||||||
|
docker kill $PSQL_DOCKER |
||||||
|
|
||||||
|
sudo chown -R $USER:$USER lib |
||||||
|
|
||||||
@ -0,0 +1,21 @@ |
|||||||
|
name = MJB-DB |
||||||
|
author = Kaitlyn Parkhurst <symkat@symkat.com> |
||||||
|
license = Perl_5 |
||||||
|
copyright_holder = Kaitlyn Parkhurst |
||||||
|
copyright_year = 2022 |
||||||
|
abstract = MyJekyllBlog's Database |
||||||
|
version = 1 |
||||||
|
|
||||||
|
[@Basic] |
||||||
|
|
||||||
|
[Prereqs] |
||||||
|
DBIx::Class::InflateColumn::Serializer = 0 |
||||||
|
DBIx::Class::Schema::Config = 0 |
||||||
|
DBIx::Class::DeploymentHandler = 0 |
||||||
|
DBIx::Class::Schema::ResultSetNames = 0 |
||||||
|
MooseX::AttributeShortcuts = 0 |
||||||
|
MooseX::Getopt = 0 |
||||||
|
Data::GUID = 0 |
||||||
|
DBD::Pg = 0 |
||||||
|
Crypt::Eksblowfish::Bcrypt = 0 |
||||||
|
Crypt::Random = 0 |
||||||
@ -0,0 +1,40 @@ |
|||||||
|
CREATE EXTENSION IF NOT EXISTS citext; |
||||||
|
|
||||||
|
CREATE TABLE person ( |
||||||
|
id serial PRIMARY KEY, |
||||||
|
name text not null, |
||||||
|
email citext not null unique, |
||||||
|
is_enabled boolean not null default true, |
||||||
|
is_admin boolean not null default false, |
||||||
|
created_at timestamptz not null default current_timestamp |
||||||
|
); |
||||||
|
|
||||||
|
-- Settings for a given user. | Use with care, add things to the data model when you should. |
||||||
|
CREATE TABLE person_settings ( |
||||||
|
id serial PRIMARY KEY, |
||||||
|
person_id int not null references person(id), |
||||||
|
name text not null, |
||||||
|
value json not null default '{}', |
||||||
|
created_at timestamptz not null default current_timestamp, |
||||||
|
|
||||||
|
-- Allow ->find_or_new_related() |
||||||
|
CONSTRAINT unq_person_id_name UNIQUE(person_id, name) |
||||||
|
); |
||||||
|
|
||||||
|
CREATE TABLE auth_password ( |
||||||
|
person_id int not null unique references person(id), |
||||||
|
password text not null, |
||||||
|
salt text not null, |
||||||
|
updated_at timestamptz not null default current_timestamp, |
||||||
|
created_at timestamptz not null default current_timestamp |
||||||
|
); |
||||||
|
|
||||||
|
CREATE TABLE auth_token ( |
||||||
|
id serial PRIMARY KEY, |
||||||
|
person_id int not null references person(id), |
||||||
|
scope text not null, |
||||||
|
token text not null, |
||||||
|
created_at timestamptz not null default current_timestamp |
||||||
|
); |
||||||
|
|
||||||
|
|
||||||
@ -0,0 +1,22 @@ |
|||||||
|
use utf8; |
||||||
|
package MJB::DB; |
||||||
|
|
||||||
|
# Created by DBIx::Class::Schema::Loader |
||||||
|
# DO NOT MODIFY THE FIRST PART OF THIS FILE |
||||||
|
|
||||||
|
use strict; |
||||||
|
use warnings; |
||||||
|
|
||||||
|
use base 'DBIx::Class::Schema'; |
||||||
|
|
||||||
|
__PACKAGE__->load_components("Schema::Config", "Schema::ResultSetNames"); |
||||||
|
|
||||||
|
__PACKAGE__->load_namespaces; |
||||||
|
|
||||||
|
|
||||||
|
# Created by DBIx::Class::Schema::Loader v0.07049 @ 2022-09-07 02:12:13 |
||||||
|
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:VjO6UzjruK0OYvT2H/KKtg |
||||||
|
|
||||||
|
|
||||||
|
# You can replace this text with custom code or comments, and it will be preserved on regeneration |
||||||
|
1; |
||||||
@ -0,0 +1,176 @@ |
|||||||
|
use utf8; |
||||||
|
package MJB::DB::Result::AuthPassword; |
||||||
|
|
||||||
|
# Created by DBIx::Class::Schema::Loader |
||||||
|
# DO NOT MODIFY THE FIRST PART OF THIS FILE |
||||||
|
|
||||||
|
=head1 NAME |
||||||
|
|
||||||
|
MJB::DB::Result::AuthPassword |
||||||
|
|
||||||
|
=cut |
||||||
|
|
||||||
|
use strict; |
||||||
|
use warnings; |
||||||
|
|
||||||
|
use base 'DBIx::Class::Core'; |
||||||
|
|
||||||
|
=head1 COMPONENTS LOADED |
||||||
|
|
||||||
|
=over 4 |
||||||
|
|
||||||
|
=item * L<DBIx::Class::InflateColumn::DateTime> |
||||||
|
|
||||||
|
=item * L<DBIx::Class::InflateColumn::Serializer> |
||||||
|
|
||||||
|
=back |
||||||
|
|
||||||
|
=cut |
||||||
|
|
||||||
|
__PACKAGE__->load_components("InflateColumn::DateTime", "InflateColumn::Serializer"); |
||||||
|
|
||||||
|
=head1 TABLE: C<auth_password> |
||||||
|
|
||||||
|
=cut |
||||||
|
|
||||||
|
__PACKAGE__->table("auth_password"); |
||||||
|
|
||||||
|
=head1 ACCESSORS |
||||||
|
|
||||||
|
=head2 person_id |
||||||
|
|
||||||
|
data_type: 'integer' |
||||||
|
is_foreign_key: 1 |
||||||
|
is_nullable: 0 |
||||||
|
|
||||||
|
=head2 password |
||||||
|
|
||||||
|
data_type: 'text' |
||||||
|
is_nullable: 0 |
||||||
|
|
||||||
|
=head2 salt |
||||||
|
|
||||||
|
data_type: 'text' |
||||||
|
is_nullable: 0 |
||||||
|
|
||||||
|
=head2 updated_at |
||||||
|
|
||||||
|
data_type: 'timestamp with time zone' |
||||||
|
default_value: current_timestamp |
||||||
|
is_nullable: 0 |
||||||
|
|
||||||
|
=head2 created_at |
||||||
|
|
||||||
|
data_type: 'timestamp with time zone' |
||||||
|
default_value: current_timestamp |
||||||
|
is_nullable: 0 |
||||||
|
|
||||||
|
=cut |
||||||
|
|
||||||
|
__PACKAGE__->add_columns( |
||||||
|
"person_id", |
||||||
|
{ data_type => "integer", is_foreign_key => 1, is_nullable => 0 }, |
||||||
|
"password", |
||||||
|
{ data_type => "text", is_nullable => 0 }, |
||||||
|
"salt", |
||||||
|
{ data_type => "text", is_nullable => 0 }, |
||||||
|
"updated_at", |
||||||
|
{ |
||||||
|
data_type => "timestamp with time zone", |
||||||
|
default_value => \"current_timestamp", |
||||||
|
is_nullable => 0, |
||||||
|
}, |
||||||
|
"created_at", |
||||||
|
{ |
||||||
|
data_type => "timestamp with time zone", |
||||||
|
default_value => \"current_timestamp", |
||||||
|
is_nullable => 0, |
||||||
|
}, |
||||||
|
); |
||||||
|
|
||||||
|
=head1 UNIQUE CONSTRAINTS |
||||||
|
|
||||||
|
=head2 C<auth_password_person_id_key> |
||||||
|
|
||||||
|
=over 4 |
||||||
|
|
||||||
|
=item * L</person_id> |
||||||
|
|
||||||
|
=back |
||||||
|
|
||||||
|
=cut |
||||||
|
|
||||||
|
__PACKAGE__->add_unique_constraint("auth_password_person_id_key", ["person_id"]); |
||||||
|
|
||||||
|
=head1 RELATIONS |
||||||
|
|
||||||
|
=head2 person |
||||||
|
|
||||||
|
Type: belongs_to |
||||||
|
|
||||||
|
Related object: L<MJB::DB::Result::Person> |
||||||
|
|
||||||
|
=cut |
||||||
|
|
||||||
|
__PACKAGE__->belongs_to( |
||||||
|
"person", |
||||||
|
"MJB::DB::Result::Person", |
||||||
|
{ id => "person_id" }, |
||||||
|
{ is_deferrable => 0, on_delete => "NO ACTION", on_update => "NO ACTION" }, |
||||||
|
); |
||||||
|
|
||||||
|
|
||||||
|
# Created by DBIx::Class::Schema::Loader v0.07049 @ 2022-09-07 02:12:13 |
||||||
|
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:y9fTRaD/zpn3Z+KL3HZv1Q |
||||||
|
|
||||||
|
__PACKAGE__->set_primary_key('person_id'); |
||||||
|
|
||||||
|
use Crypt::Eksblowfish::Bcrypt qw( bcrypt_hash en_base64 de_base64 ); |
||||||
|
use Crypt::Random; |
||||||
|
|
||||||
|
sub check_password { |
||||||
|
my ( $self, $password ) = @_; |
||||||
|
return de_base64($self->password) eq bcrypt_hash({ |
||||||
|
key_nul => 1, |
||||||
|
cost => 8, |
||||||
|
salt => de_base64($self->salt), |
||||||
|
}, $password ); |
||||||
|
} |
||||||
|
|
||||||
|
sub set_password { |
||||||
|
my ( $self, $password ) = @_; |
||||||
|
$self->_fill_password( $password ); |
||||||
|
$self->insert; |
||||||
|
return $self; |
||||||
|
} |
||||||
|
|
||||||
|
sub update_password { |
||||||
|
my ( $self, $password ) = @_; |
||||||
|
$self->_fill_password( $password ); |
||||||
|
$self->update; |
||||||
|
return $self; |
||||||
|
} |
||||||
|
|
||||||
|
sub _fill_password { |
||||||
|
my ( $self, $password ) = @_; |
||||||
|
|
||||||
|
my $salt = random_salt(); |
||||||
|
|
||||||
|
$self->password( |
||||||
|
en_base64( |
||||||
|
bcrypt_hash({ |
||||||
|
key_nul => 1, |
||||||
|
cost => 8, |
||||||
|
salt => $salt, |
||||||
|
}, $password ) |
||||||
|
) |
||||||
|
); |
||||||
|
|
||||||
|
$self->salt( en_base64($salt) ); |
||||||
|
} |
||||||
|
|
||||||
|
sub random_salt { |
||||||
|
Crypt::Random::makerandom_octet( Length => 16 ); |
||||||
|
} |
||||||
|
|
||||||
|
1; |
||||||
@ -0,0 +1,128 @@ |
|||||||
|
use utf8; |
||||||
|
package MJB::DB::Result::AuthToken; |
||||||
|
|
||||||
|
# Created by DBIx::Class::Schema::Loader |
||||||
|
# DO NOT MODIFY THE FIRST PART OF THIS FILE |
||||||
|
|
||||||
|
=head1 NAME |
||||||
|
|
||||||
|
MJB::DB::Result::AuthToken |
||||||
|
|
||||||
|
=cut |
||||||
|
|
||||||
|
use strict; |
||||||
|
use warnings; |
||||||
|
|
||||||
|
use base 'DBIx::Class::Core'; |
||||||
|
|
||||||
|
=head1 COMPONENTS LOADED |
||||||
|
|
||||||
|
=over 4 |
||||||
|
|
||||||
|
=item * L<DBIx::Class::InflateColumn::DateTime> |
||||||
|
|
||||||
|
=item * L<DBIx::Class::InflateColumn::Serializer> |
||||||
|
|
||||||
|
=back |
||||||
|
|
||||||
|
=cut |
||||||
|
|
||||||
|
__PACKAGE__->load_components("InflateColumn::DateTime", "InflateColumn::Serializer"); |
||||||
|
|
||||||
|
=head1 TABLE: C<auth_token> |
||||||
|
|
||||||
|
=cut |
||||||
|
|
||||||
|
__PACKAGE__->table("auth_token"); |
||||||
|
|
||||||
|
=head1 ACCESSORS |
||||||
|
|
||||||
|
=head2 id |
||||||
|
|
||||||
|
data_type: 'integer' |
||||||
|
is_auto_increment: 1 |
||||||
|
is_nullable: 0 |
||||||
|
sequence: 'auth_token_id_seq' |
||||||
|
|
||||||
|
=head2 person_id |
||||||
|
|
||||||
|
data_type: 'integer' |
||||||
|
is_foreign_key: 1 |
||||||
|
is_nullable: 0 |
||||||
|
|
||||||
|
=head2 scope |
||||||
|
|
||||||
|
data_type: 'text' |
||||||
|
is_nullable: 0 |
||||||
|
|
||||||
|
=head2 token |
||||||
|
|
||||||
|
data_type: 'text' |
||||||
|
is_nullable: 0 |
||||||
|
|
||||||
|
=head2 created_at |
||||||
|
|
||||||
|
data_type: 'timestamp with time zone' |
||||||
|
default_value: current_timestamp |
||||||
|
is_nullable: 0 |
||||||
|
|
||||||
|
=cut |
||||||
|
|
||||||
|
__PACKAGE__->add_columns( |
||||||
|
"id", |
||||||
|
{ |
||||||
|
data_type => "integer", |
||||||
|
is_auto_increment => 1, |
||||||
|
is_nullable => 0, |
||||||
|
sequence => "auth_token_id_seq", |
||||||
|
}, |
||||||
|
"person_id", |
||||||
|
{ data_type => "integer", is_foreign_key => 1, is_nullable => 0 }, |
||||||
|
"scope", |
||||||
|
{ data_type => "text", is_nullable => 0 }, |
||||||
|
"token", |
||||||
|
{ data_type => "text", is_nullable => 0 }, |
||||||
|
"created_at", |
||||||
|
{ |
||||||
|
data_type => "timestamp with time zone", |
||||||
|
default_value => \"current_timestamp", |
||||||
|
is_nullable => 0, |
||||||
|
}, |
||||||
|
); |
||||||
|
|
||||||
|
=head1 PRIMARY KEY |
||||||
|
|
||||||
|
=over 4 |
||||||
|
|
||||||
|
=item * L</id> |
||||||
|
|
||||||
|
=back |
||||||
|
|
||||||
|
=cut |
||||||
|
|
||||||
|
__PACKAGE__->set_primary_key("id"); |
||||||
|
|
||||||
|
=head1 RELATIONS |
||||||
|
|
||||||
|
=head2 person |
||||||
|
|
||||||
|
Type: belongs_to |
||||||
|
|
||||||
|
Related object: L<MJB::DB::Result::Person> |
||||||
|
|
||||||
|
=cut |
||||||
|
|
||||||
|
__PACKAGE__->belongs_to( |
||||||
|
"person", |
||||||
|
"MJB::DB::Result::Person", |
||||||
|
{ id => "person_id" }, |
||||||
|
{ is_deferrable => 0, on_delete => "NO ACTION", on_update => "NO ACTION" }, |
||||||
|
); |
||||||
|
|
||||||
|
|
||||||
|
# Created by DBIx::Class::Schema::Loader v0.07049 @ 2022-09-07 02:12:13 |
||||||
|
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:QswwNuQ8rXDUWbDi3kaEYA |
||||||
|
|
||||||
|
|
||||||
|
# You can replace this text with custom code or comments, and it will be preserved on regeneration |
||||||
|
1; |
||||||
@ -0,0 +1,233 @@ |
|||||||
|
use utf8; |
||||||
|
package MJB::DB::Result::Person; |
||||||
|
|
||||||
|
# Created by DBIx::Class::Schema::Loader |
||||||
|
# DO NOT MODIFY THE FIRST PART OF THIS FILE |
||||||
|
|
||||||
|
=head1 NAME |
||||||
|
|
||||||
|
MJB::DB::Result::Person |
||||||
|
|
||||||
|
=cut |
||||||
|
|
||||||
|
use strict; |
||||||
|
use warnings; |
||||||
|
|
||||||
|
use base 'DBIx::Class::Core'; |
||||||
|
|
||||||
|
=head1 COMPONENTS LOADED |
||||||
|
|
||||||
|
=over 4 |
||||||
|
|
||||||
|
=item * L<DBIx::Class::InflateColumn::DateTime> |
||||||
|
|
||||||
|
=item * L<DBIx::Class::InflateColumn::Serializer> |
||||||
|
|
||||||
|
=back |
||||||
|
|
||||||
|
=cut |
||||||
|
|
||||||
|
__PACKAGE__->load_components("InflateColumn::DateTime", "InflateColumn::Serializer"); |
||||||
|
|
||||||
|
=head1 TABLE: C<person> |
||||||
|
|
||||||
|
=cut |
||||||
|
|
||||||
|
__PACKAGE__->table("person"); |
||||||
|
|
||||||
|
=head1 ACCESSORS |
||||||
|
|
||||||
|
=head2 id |
||||||
|
|
||||||
|
data_type: 'integer' |
||||||
|
is_auto_increment: 1 |
||||||
|
is_nullable: 0 |
||||||
|
sequence: 'person_id_seq' |
||||||
|
|
||||||
|
=head2 name |
||||||
|
|
||||||
|
data_type: 'text' |
||||||
|
is_nullable: 0 |
||||||
|
|
||||||
|
=head2 email |
||||||
|
|
||||||
|
data_type: 'citext' |
||||||
|
is_nullable: 0 |
||||||
|
|
||||||
|
=head2 is_enabled |
||||||
|
|
||||||
|
data_type: 'boolean' |
||||||
|
default_value: true |
||||||
|
is_nullable: 0 |
||||||
|
|
||||||
|
=head2 is_admin |
||||||
|
|
||||||
|
data_type: 'boolean' |
||||||
|
default_value: false |
||||||
|
is_nullable: 0 |
||||||
|
|
||||||
|
=head2 created_at |
||||||
|
|
||||||
|
data_type: 'timestamp with time zone' |
||||||
|
default_value: current_timestamp |
||||||
|
is_nullable: 0 |
||||||
|
|
||||||
|
=cut |
||||||
|
|
||||||
|
__PACKAGE__->add_columns( |
||||||
|
"id", |
||||||
|
{ |
||||||
|
data_type => "integer", |
||||||
|
is_auto_increment => 1, |
||||||
|
is_nullable => 0, |
||||||
|
sequence => "person_id_seq", |
||||||
|
}, |
||||||
|
"name", |
||||||
|
{ data_type => "text", is_nullable => 0 }, |
||||||
|
"email", |
||||||
|
{ data_type => "citext", is_nullable => 0 }, |
||||||
|
"is_enabled", |
||||||
|
{ data_type => "boolean", default_value => \"true", is_nullable => 0 }, |
||||||
|
"is_admin", |
||||||
|
{ data_type => "boolean", default_value => \"false", is_nullable => 0 }, |
||||||
|
"created_at", |
||||||
|
{ |
||||||
|
data_type => "timestamp with time zone", |
||||||
|
default_value => \"current_timestamp", |
||||||
|
is_nullable => 0, |
||||||
|
}, |
||||||
|
); |
||||||
|
|
||||||
|
=head1 PRIMARY KEY |
||||||
|
|
||||||
|
=over 4 |
||||||
|
|
||||||
|
=item * L</id> |
||||||
|
|
||||||
|
=back |
||||||
|
|
||||||
|
=cut |
||||||
|
|
||||||
|
__PACKAGE__->set_primary_key("id"); |
||||||
|
|
||||||
|
=head1 UNIQUE CONSTRAINTS |
||||||
|
|
||||||
|
=head2 C<person_email_key> |
||||||
|
|
||||||
|
=over 4 |
||||||
|
|
||||||
|
=item * L</email> |
||||||
|
|
||||||
|
=back |
||||||
|
|
||||||
|
=cut |
||||||
|
|
||||||
|
__PACKAGE__->add_unique_constraint("person_email_key", ["email"]); |
||||||
|
|
||||||
|
=head1 RELATIONS |
||||||
|
|
||||||
|
=head2 auth_password |
||||||
|
|
||||||
|
Type: might_have |
||||||
|
|
||||||
|
Related object: L<MJB::DB::Result::AuthPassword> |
||||||
|
|
||||||
|
=cut |
||||||
|
|
||||||
|
__PACKAGE__->might_have( |
||||||
|
"auth_password", |
||||||
|
"MJB::DB::Result::AuthPassword", |
||||||
|
{ "foreign.person_id" => "self.id" }, |
||||||
|
{ cascade_copy => 0, cascade_delete => 0 }, |
||||||
|
); |
||||||
|
|
||||||
|
=head2 auth_tokens |
||||||
|
|
||||||
|
Type: has_many |
||||||
|
|
||||||
|
Related object: L<MJB::DB::Result::AuthToken> |
||||||
|
|
||||||
|
=cut |
||||||
|
|
||||||
|
__PACKAGE__->has_many( |
||||||
|
"auth_tokens", |
||||||
|
"MJB::DB::Result::AuthToken", |
||||||
|
{ "foreign.person_id" => "self.id" }, |
||||||
|
{ cascade_copy => 0, cascade_delete => 0 }, |
||||||
|
); |
||||||
|
|
||||||
|
=head2 person_settings |
||||||
|
|
||||||
|
Type: has_many |
||||||
|
|
||||||
|
Related object: L<MJB::DB::Result::PersonSetting> |
||||||
|
|
||||||
|
=cut |
||||||
|
|
||||||
|
__PACKAGE__->has_many( |
||||||
|
"person_settings", |
||||||
|
"MJB::DB::Result::PersonSetting", |
||||||
|
{ "foreign.person_id" => "self.id" }, |
||||||
|
{ cascade_copy => 0, cascade_delete => 0 }, |
||||||
|
); |
||||||
|
|
||||||
|
|
||||||
|
# Created by DBIx::Class::Schema::Loader v0.07049 @ 2022-09-07 02:12:13 |
||||||
|
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:t8nEGpGF7PyRX9J3V7R9Rw |
||||||
|
|
||||||
|
use Data::GUID; |
||||||
|
|
||||||
|
sub setting { |
||||||
|
my ( $self, $setting, $value ) = @_; |
||||||
|
|
||||||
|
if ( defined $value ) { |
||||||
|
my $rs = $self->find_or_new_related( 'person_settings', { name => $setting } ); |
||||||
|
$rs->value( ref $value ? $value : { value => $value } ); |
||||||
|
|
||||||
|
$rs->update if $rs->in_storage; |
||||||
|
$rs->insert unless $rs->in_storage; |
||||||
|
|
||||||
|
return $value; |
||||||
|
} else { |
||||||
|
my $result = $self->find_related('person_settings', { name => $setting }); |
||||||
|
return undef unless $result; |
||||||
|
return $self->_get_setting_value($result); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
sub _get_setting_value { |
||||||
|
my ( $self, $setting ) = @_; |
||||||
|
|
||||||
|
if ( ref $setting->value eq 'HASH' and keys %{$setting->value} == 1 and exists $setting->value->{value} ) { |
||||||
|
return $setting->value->{value}; |
||||||
|
} |
||||||
|
|
||||||
|
return $setting->value; |
||||||
|
} |
||||||
|
|
||||||
|
sub get_settings { |
||||||
|
my ( $self ) = @_; |
||||||
|
|
||||||
|
my $return = {}; |
||||||
|
|
||||||
|
foreach my $setting ( $self->search_related( 'person_settings', {} )->all ) { |
||||||
|
$return->{${\($setting->name)}} = $self->_get_setting_value($setting); |
||||||
|
} |
||||||
|
|
||||||
|
return $return; |
||||||
|
} |
||||||
|
|
||||||
|
sub create_auth_token { |
||||||
|
my ( $self, $scope ) = @_; |
||||||
|
|
||||||
|
my $token = Data::GUID->guid_string; |
||||||
|
|
||||||
|
$self->create_related( 'auth_tokens', { |
||||||
|
token => $token, |
||||||
|
scope => $scope, |
||||||
|
}); |
||||||
|
|
||||||
|
return $token; |
||||||
|
} |
||||||
|
|
||||||
|
1; |
||||||
@ -0,0 +1,151 @@ |
|||||||
|
use utf8; |
||||||
|
package MJB::DB::Result::PersonSetting; |
||||||
|
|
||||||
|
# Created by DBIx::Class::Schema::Loader |
||||||
|
# DO NOT MODIFY THE FIRST PART OF THIS FILE |
||||||
|
|
||||||
|
=head1 NAME |
||||||
|
|
||||||
|
MJB::DB::Result::PersonSetting |
||||||
|
|
||||||
|
=cut |
||||||
|
|
||||||
|
use strict; |
||||||
|
use warnings; |
||||||
|
|
||||||
|
use base 'DBIx::Class::Core'; |
||||||
|
|
||||||
|
=head1 COMPONENTS LOADED |
||||||
|
|
||||||
|
=over 4 |
||||||
|
|
||||||
|
=item * L<DBIx::Class::InflateColumn::DateTime> |
||||||
|
|
||||||
|
=item * L<DBIx::Class::InflateColumn::Serializer> |
||||||
|
|
||||||
|
=back |
||||||
|
|
||||||
|
=cut |
||||||
|
|
||||||
|
__PACKAGE__->load_components("InflateColumn::DateTime", "InflateColumn::Serializer"); |
||||||
|
|
||||||
|
=head1 TABLE: C<person_settings> |
||||||
|
|
||||||
|
=cut |
||||||
|
|
||||||
|
__PACKAGE__->table("person_settings"); |
||||||
|
|
||||||
|
=head1 ACCESSORS |
||||||
|
|
||||||
|
=head2 id |
||||||
|
|
||||||
|
data_type: 'integer' |
||||||
|
is_auto_increment: 1 |
||||||
|
is_nullable: 0 |
||||||
|
sequence: 'person_settings_id_seq' |
||||||
|
|
||||||
|
=head2 person_id |
||||||
|
|
||||||
|
data_type: 'integer' |
||||||
|
is_foreign_key: 1 |
||||||
|
is_nullable: 0 |
||||||
|
|
||||||
|
=head2 name |
||||||
|
|
||||||
|
data_type: 'text' |
||||||
|
is_nullable: 0 |
||||||
|
|
||||||
|
=head2 value |
||||||
|
|
||||||
|
data_type: 'json' |
||||||
|
default_value: '{}' |
||||||
|
is_nullable: 0 |
||||||
|
serializer_class: 'JSON' |
||||||
|
|
||||||
|
=head2 created_at |
||||||
|
|
||||||
|
data_type: 'timestamp with time zone' |
||||||
|
default_value: current_timestamp |
||||||
|
is_nullable: 0 |
||||||
|
|
||||||
|
=cut |
||||||
|
|
||||||
|
__PACKAGE__->add_columns( |
||||||
|
"id", |
||||||
|
{ |
||||||
|
data_type => "integer", |
||||||
|
is_auto_increment => 1, |
||||||
|
is_nullable => 0, |
||||||
|
sequence => "person_settings_id_seq", |
||||||
|
}, |
||||||
|
"person_id", |
||||||
|
{ data_type => "integer", is_foreign_key => 1, is_nullable => 0 }, |
||||||
|
"name", |
||||||
|
{ data_type => "text", is_nullable => 0 }, |
||||||
|
"value", |
||||||
|
{ |
||||||
|
data_type => "json", |
||||||
|
default_value => "{}", |
||||||
|
is_nullable => 0, |
||||||
|
serializer_class => "JSON", |
||||||
|
}, |
||||||
|
"created_at", |
||||||
|
{ |
||||||
|
data_type => "timestamp with time zone", |
||||||
|
default_value => \"current_timestamp", |
||||||
|
is_nullable => 0, |
||||||
|
}, |
||||||
|
); |
||||||
|
|
||||||
|
=head1 PRIMARY KEY |
||||||
|
|
||||||
|
=over 4 |
||||||
|
|
||||||
|
=item * L</id> |
||||||
|
|
||||||
|
=back |
||||||
|
|
||||||
|
=cut |
||||||
|
|
||||||
|
__PACKAGE__->set_primary_key("id"); |
||||||
|
|
||||||
|
=head1 UNIQUE CONSTRAINTS |
||||||
|
|
||||||
|
=head2 C<unq_person_id_name> |
||||||
|
|
||||||
|
=over 4 |
||||||
|
|
||||||
|
=item * L</person_id> |
||||||
|
|
||||||
|
=item * L</name> |
||||||
|
|
||||||
|
=back |
||||||
|
|
||||||
|
=cut |
||||||
|
|
||||||
|
__PACKAGE__->add_unique_constraint("unq_person_id_name", ["person_id", "name"]); |
||||||
|
|
||||||
|
=head1 RELATIONS |
||||||
|
|
||||||
|
=head2 person |
||||||
|
|
||||||
|
Type: belongs_to |
||||||
|
|
||||||
|
Related object: L<MJB::DB::Result::Person> |
||||||
|
|
||||||
|
=cut |
||||||
|
|
||||||
|
__PACKAGE__->belongs_to( |
||||||
|
"person", |
||||||
|
"MJB::DB::Result::Person", |
||||||
|
{ id => "person_id" }, |
||||||
|
{ is_deferrable => 0, on_delete => "NO ACTION", on_update => "NO ACTION" }, |
||||||
|
); |
||||||
|
|
||||||
|
|
||||||
|
# Created by DBIx::Class::Schema::Loader v0.07049 @ 2022-09-07 02:12:13 |
||||||
|
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:up8WXyHIVQXePFBYFKs5xA |
||||||
|
|
||||||
|
|
||||||
|
# You can replace this text with custom code or comments, and it will be preserved on regeneration |
||||||
|
1; |
||||||
Loading…
Reference in new issue