package Lemonldap::NG::Portal::Auth::WebID;

use strict;
use Mouse;
use Regexp::Assemble;
use Web::ID;
use Lemonldap::NG::Portal::Main::Constants qw(
  PE_BADCERTIFICATE
  PE_BADCREDENTIALS
  PE_BADPARTNER
  PE_CERTIFICATEREQUIRED
  PE_OK
);

our $VERSION = '2.0.0';

extends 'Lemonldap::NG::Portal::Main::Auth';

# PROPERTIES

has SSLField => (
    is      => 'rw',
    lazy    => 1,
    default => sub {
        return ( $_[0]->{conf}->{SSLVar} || 'SSL_CLIENT_S_DN_Email' );
    }
);

has reWebIDWhitelist => ( is => 'rw' );

# INITIALIZATION

sub init {
    my ($self) = @_;
    my @hosts = split /\s+/, $self->{conf}->{webIDWhitelist};
    unless (@hosts) {
        $self->error(
'WebID white list is empty. Set it in manager, use * to accept all FOAF providers'
        );
        return 0;
    }
    my $re = Regexp::Assemble->new();
    foreach my $h (@hosts) {
        $self->logger->debug("Add $h in WebID whitelist");
        $h = quotemeta($h);
        $h =~ s/\\\*/\.\*\?/g;
        $re->add($h);
    }
    my $reString = '^https?://' . $re->as_string . '(?:/.*|)$';
    $self->reWebIDWhitelist(qr($reString));
    return 1;
}

# Read username in SSL environment variables, or return an error
# @return Lemonldap::NG::Portal constant
sub extractFormInfo {
    my ( $self, $req ) = @_;

    # 1. Verify SSL exchange
    unless ( $req->{SSL_CLIENT_S_DN} ) {
        $self->userLogger->warn( 'No certificate found for ' . $req->address );
        return PE_CERTIFICATEREQUIRED;
    }

    # 2. Verify that certificate is WebID compliant
    #    NB: WebID URI is used as user field
    eval {
        $req->data->{_webid} =
          Web::ID->new( certificate => $req->{SSL_CLIENT_CERT} );
        $req->user( $req->data->{_webid}->uri->as_string );
    };
    return PE_BADCERTIFICATE if ( $@ or not( $req->user ) );

    # 3. Verify that FOAF host is in white list
    return PE_BADPARTNER unless ( $req->user =~ $self->reWebIDWhitelist );

    # 4. Verify FOAF document
    return PE_BADCREDENTIALS unless ( $req->data->{_webid}->valid() );
    $req->data->{_webIdAuthDone}++;

    # 5. OK, access granted
    return PE_OK;
}

sub authenticate {
    PE_OK;
}

sub setAuthSessionInfo {
    my ( $self, $req ) = @_;
    $req->{sessionInfo}->{authenticationLevel} = $self->conf->{webIDAuthnLevel};
    PE_OK;
}

sub getDisplayType {
    return "logo";
}

1;
