<commit_before>package Arepa::Web::Auth;

use strict;
use warnings;

use English qw(-no_match_vars);
use base 'Arepa::Web::Base';
use DBI;
use Digest::MD5;
use YAML;
use MojoX::Session;

# Let session cookies live one week
use constant TTL_SESSION_COOKIE => 60 * 60 * 24 * 7;

sub _check_credentials {
    my ($self, $username, $password, $auth_type) = @_;

    if ($auth_type eq 'file_md5') {
        my $user_file_path =
          $self->config->get_key('web_ui:authentication:user_file');
        my %users = %{YAML::LoadFile($user_file_path)};
        return ($users{users}->{$username} eq Digest::MD5::md5_hex($password));
    }
    elsif (!defined $auth_type) {
        my %users = %{YAML::LoadFile($self->config->
                                            get_key('web_ui:user_file'))};
        return ($users{$username} eq Digest::MD5::md5_hex($password));
    }
    else {
        die "Broken configuration: unknown auth type '$auth_type'\n";
    }
}

sub _get_session {
    my ($self) = @_;

    my $session_db = $self->config->get_key('web_ui:session_db');
    my $dbh = DBI->connect("dbi:SQLite:dbname=$session_db");
    my $session = MojoX::Session->new(tx            => $self->tx,
                                      store         => [dbi => {dbh => $dbh}],
                                      expires_delta => TTL_SESSION_COOKIE);

    # Don't check anything for public URLs
    my $url_parts = $self->tx->req->url->path->parts;
    if (scalar @$url_parts && $url_parts->[0] eq 'public') {
        $session->load;
        return $session;
    }

    # External authentication
    my $auth_type_key = 'web_ui:authentication:type';
    my $auth_type;
    if ($self->config->key_exists($auth_type_key)) {
        $auth_type = $self->config->get_key($auth_type_key);
    }

    if ($auth_type eq 'external') {
        if ($ENV{REMOTE_USER}) {
            $session->load;
            if (! $session->sid || $session->is_expired) {
                $session->create;
                $session->flush;
            }
        }
        else {
            $self->vars("error" => "Authentication error: your webserver is " .
                                       "not passing the REMOTE_USER " .
                                       "environment variable to the " .
                                       "application");
        }
    }
    else {
        if (defined $self->param('username') &&
                defined $self->param('password')) {
            my $valid_creds;
            eval {
                $valid_creds =
                  $self->_check_credentials($self->param('username'),
                                            $self->param('password'),
                                            $auth_type);
            };
            if ($EVAL_ERROR) {
                $self->vars("error" => $EVAL_ERROR);
            }
            else {
                if ($valid_creds) {
                    $session->create;
                    $session->flush;
                }
                else {
                    $self->vars("error" => "Invalid username or password");
                }
            }
        } else {
            $session->load;
        }
    }

    return $session;
}

sub login {
    my $self = shift;

    my $session = $self->_get_session;

    if ($session->sid) {
        return 1;
    }
    $self->vars();
    $self->render('auth/login', layout => 'default');
    return 0;
}

sub logout {
    my $self = shift;
<commit_msg>Check if the user is an admin, set is_user_admin accordingly in the stash<commit_after>package Arepa::Web::Auth;

use strict;
use warnings;

use English qw(-no_match_vars);
use base 'Arepa::Web::Base';
use DBI;
use Digest::MD5;
use YAML;
use MojoX::Session;

# Let session cookies live one week
use constant TTL_SESSION_COOKIE => 60 * 60 * 24 * 7;

sub _check_credentials {
    my ($self, $username, $password, $auth_type) = @_;

    if ($auth_type eq 'file_md5') {
        my $user_file_path =
          $self->config->get_key('web_ui:authentication:user_file');
        my %users = %{YAML::LoadFile($user_file_path)};
        my ($valid_credentials, $is_admin) =
          ($users{users}->{$username} eq Digest::MD5::md5_hex($password),
           scalar(grep { $_ eq $username } @{$users{admins}}));
        return ($valid_credentials, $is_admin);
    }
    elsif (!defined $auth_type) {
        my %users = %{YAML::LoadFile($self->config->
                                            get_key('web_ui:user_file'))};
        my $valid_credentials =
          $users{$username} eq Digest::MD5::md5_hex($password);
        return ($valid_credentials, 1);
    }
    else {
        die "Broken configuration: unknown auth type '$auth_type'\n";
    }
}

sub _get_session {
    my ($self) = @_;

    my $session_db = $self->config->get_key('web_ui:session_db');
    my $dbh = DBI->connect("dbi:SQLite:dbname=$session_db");
    my $session = MojoX::Session->new(tx            => $self->tx,
                                      store         => [dbi => {dbh => $dbh}],
                                      expires_delta => TTL_SESSION_COOKIE);


    # Don't check anything for public URLs
    my $url_parts = $self->tx->req->url->path->parts;
    if (scalar @$url_parts && $url_parts->[0] eq 'public') {
        $session->load;
        return $session;
    }

    # External authentication
    my $auth_type_key = 'web_ui:authentication:type';
    my $auth_type;
    if ($self->config->key_exists($auth_type_key)) {
        $auth_type = $self->config->get_key($auth_type_key);
    }

    if ($auth_type eq 'external') {
        if ($ENV{REMOTE_USER}) {
            $session->load;
            if (! $session->sid || $session->is_expired) {
                $session->create;
                $session->flush;

                # Figure out if the logged in user is an admin
                my $user_file_path =
                  $self->config->get_key('web_ui:authentication:user_file');
                my %users = %{YAML::LoadFile($user_file_path)};
                my $is_admin = scalar(grep { $_ eq $ENV{REMOTE_USER} }
                                           @{$users{admins}});
                $self->stash(username      => $ENV{REMOTE_USER},
                             is_user_admin => $is_admin);
            }
        }
        else {
            $self->vars("error" => "Authentication error: your webserver is " .
                                       "not passing the REMOTE_USER " .
                                       "environment variable to the " .
                                       "application");
        }
    }
    else {
        if (defined $self->param('username') &&
                defined $self->param('password')) {
            my ($valid_creds, $is_admin);
            eval {
                ($valid_creds, $is_admin) =
                  $self->_check_credentials($self->param('username'),
                                            $self->param('password'),
                                            $auth_type);
            };
            if ($EVAL_ERROR) {
                $self->vars("error" => $EVAL_ERROR);
            }
            else {
                if ($valid_creds) {
                    $session->create;
                    $session->flush;
                    $self->stash(username      => $self->param('username'),
                                 is_user_admin => $is_admin);
                }
                else {
                    $self->vars("error" => "Invalid username or password");
                }
            }
        } else {
            $session->load;
        }
    }

    return $session;
}

sub login {
    my $self = shift;

    my $session = $self->_get_session;

    if ($session->sid) {
        return 1;
    }
    $self->vars();
    $self->render('auth/login', layout => 'default');
    return 0;
}

sub logout {
    my $self = shift;

{'fraction_non_alphanumeric': 0.1402129817444219, 'fraction_numerical': 0.004183569979716024, 'mean_word_length': 1.5925073940190602, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 114, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 27, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4700169', 'n_tokens_mistral': 2386, 'n_tokens_neox': 2277, 'n_words': 467}