package MyRedland::Lusers; use v5.34.1; use strict; use warnings; use DateTime; use DateTime::Format::Pg; use Moo; use Crypt::URandom; use Types::Standard qw/InstanceOf Str ArrayRef/; use Params::ValidationCompiler qw/validation_for/; use MyRedland::DB; use MyRedland::Luser; use List::AllUtils qw/any/; my $fpg = DateTime::Format::Pg->new; my @FIELDS = qw/uuid username email verified password mail_verification_payload avatar mail_verification_expiration creation_date last_access stripe_customer_id/; has app => ( is => 'rw', isa => InstanceOf ['Mojolicious'], required => 1, ); has dbh => ( is => 'lazy', ); sub _build_dbh { my $self = shift; return MyRedland::DB->connect( $self->app ); } { my $validator = validation_for( params => { username => { type => Str }, email => { type => Str }, password => { type => Str }, } ); sub create { my $self = shift; my %params = $validator->(@_); my $dbh = $self->dbh; my $username = $params{username}; my $email = $params{email}; my $password = $params{password}; my $test_mode = $self->app->config->{test_mode}; my $verified = 0; if ($test_mode) { $verified = 1; } my $mail_verification_payload = unpack 'H*', Crypt::URandom::urandom(30); my $avatar = ''; my $mail_verification_expiration = $fpg->format_datetime( DateTime->now->add( days => 1 ) ); my $user_hash = $dbh->selectrow_hashref( <<"EOF", undef, $username, $email, $verified, $password, $mail_verification_payload, $avatar, $mail_verification_expiration ); INSERT INTO lusers (username, email, verified, password, mail_verification_payload, avatar, mail_verification_expiration) VALUES (?, ?, ?, ?, ?, ?, ?) RETURNING @{[join ', ', @FIELDS]}; EOF $self->_convert_user_hash_dates($user_hash); my $user = MyRedland::Luser->new(%$user_hash); return $user; } } { my $validator = validation_for( params => { user => { type => InstanceOf ['MyRedland::Luser'] }, fields => { type => ArrayRef [Str] }, } ); sub update { my $self = shift; my %params = $validator->(@_); my $user = $params{user}; my $fields = $params{fields}; my %updates; for my $field (@$fields) { if ( any { $field eq $_ } qw/verified email password mail_verification_expiration mail_verification_payload last_access avatar stripe_customer_id/) { $updates{$field} = $user->$field; next; } die "No such field $field."; } my $query = <<"EOF"; UPDATE lusers SET @{[ join ', ', map { "$_ = ?" } @$fields ]} WHERE uuid = ? RETURNING @{[join ', ', @FIELDS]}; EOF my $dbh = $self->dbh; my $user_hash = $dbh->selectrow_hashref($query, undef, @updates{@$fields}, $user->uuid); $self->_convert_user_hash_dates($user_hash); $user = MyRedland::Luser->new(%$user_hash); return $user; } } sub _convert_user_hash_dates { my $self = shift; my $user_hash = shift; $user_hash->{mail_verification_expiration} = $fpg->parse_datetime( $user_hash->{mail_verification_expiration} ); $user_hash->{creation_date} = $fpg->parse_datetime( $user_hash->{creation_date} ); $user_hash->{last_access} = $fpg->parse_datetime( $user_hash->{last_access} ); } { my $validator = validation_for( params => { uuid => { type => Str }, } ); sub find_by_uuid { my $self = shift; my %params = $validator->(@_); my $uuid = $params{uuid}; my $dbh = $self->dbh; my $user_hash = $dbh->selectrow_hashref( <<"EOF", undef, $uuid ); SELECT @{[join ', ', @FIELDS]} FROM lusers where uuid = ?; EOF if ( !defined $user_hash ) { return; } $self->_convert_user_hash_dates($user_hash); my $user = MyRedland::Luser->new(%$user_hash); return $user; } } { my $validator = validation_for( params => { username => { type => Str }, } ); sub find_by_username { my $self = shift; my %params = $validator->(@_); my $username = $params{username}; my $dbh = $self->dbh; my $user_hash = $dbh->selectrow_hashref( <<"EOF", undef, $username ); SELECT @{[join ', ', @FIELDS]} FROM lusers where username = ?; EOF if ( !defined $user_hash ) { return; } $self->_convert_user_hash_dates($user_hash); my $user = MyRedland::Luser->new(%$user_hash); return $user; } } 1;