---
name: "Lemonldap::NG::Portal::Main::Plugin"
section: "3pm"
platform: "linux"
package: "liblemonldap-ng-portal-perl"
version: "2.21.2+ds-1+deb13u3"
release: "Debian 13 (Trixie)"
platforms: ["linux"]
url: "https://new.carta.tech/Lemonldap::NG::Portal::Main::Plugin"
---

# Lemonldap::NG::Portal::Main::Plugin(3pm)

Base class for Lemonldap::NG::Portal modules (plugins, authentication modules,...).

## NAME

Lemonldap::NG::Portal::Main::Plugin - Base class for Lemonldap::NG::Portal modules (plugins, authentication modules,...).

## SYNOPSIS

```
  package Lemonldap::NG::Portal::My::Plugin;
  use Mouse;
  extends 'Lemonldap::NG::Portal::Main::Plugin';

  use constant beforeAuth => 'verifyIP';

  sub init {
      my ($self) = @_;
      $self->addUnauthRoute( mypath => 'hello', [ 'GET', 'PUT' ] );
      $self->addAuthRoute( mypath => 'welcome', [ 'GET', 'PUT' ] );
      return 1;
  }
  sub verifyIP {
      my ($self, $req) = @_;
      return PE_ERROR if($req->address !~ /^10/);
      return PE_OK;
  }
  sub hello {
      my ($self, $req) = @_;
      ...
      return $self->p->sendJSONresponse($req, { hello => 1 });
  }
  sub welcome {
      my ($self, $req) = @_;
      ...
      return $self->p->sendHtml($req, 'template', params => { WELCOME => 1 });
  }
```

## DESCRIPTION

Lemonldap::NG::Portal::Main::Plugin provides many methods to easily write  Lemonldap::NG addons.

**init()** is called for each plugin. If a plugin initialization fails (**init()** returns 0), the portal responds a 500 status code for each request.

## Writing plugins

Custom plugins can be inserted in portal by declaring them in `"lemonldap-ng.ini"` file, section `"[portal]"`, key `"customPlugins"`:

```
  [portal]
  customPlugins = ::My::Plugin1, ::My::Plugin2
```

Plugins must be valid packages well found in `@INC`.

### Plugin entry points

*Entry point based on PATH\_INFO*

Plugins can declare unauthRoutes/authRoutes during initialization (= /path/info). Methods declared in this way must be declared in the plugin class. They will be called with `$req` argument. `$req` is the HTTP request. (See Lemonldap::NG::Portal::Main::Request). These methods must return a valid PSGI response. You can also use **sendJSONresponse()** or **sendHtml()** methods (see Lemonldap::NG::Common::PSGI).

Example:

```
  sub init {
      my ($self) = @_;
      $self->addUnauthRoute( mypath => 'hello', [ 'GET', 'PUT' ] );
      $self->addAuthRoute( mypath => 'welcome', [ 'GET', 'PUT' ] );
      return 1;
  }
  sub hello {
      my ($self, $req) = @_;
      ...
      return $self->p->sendJSONresponse($req, { hello => 1 });
  }
  sub welcome {
      my ($self, $req) = @_;
      ...
      return $self->p->sendHtml($req, 'template', params => { WELLCOME => 1 });
  }
```

If you want to get a "protected application" behavior, you can use **addAuthRouteWithRedirect**. This methods calls **addAuthRoute** with given arguments and build a "unAuth" route that build a redirection after authentication.

*Entry point in auth process*

A plugin which wants to be inserted in authentication process has to declare constants set with method name to run. Following entry points are available.

- "beforeAuth": method called before authentication process

  - "betweenAuthAndData": method called after authentication and before setting "sessionInfo" provisionning

  - "afterData": method called after "sessionInfo" provisionning *(macros, groups,...)*. This entry point is called after 'storeHistory' if login process fails and before 'validSession' if succeeds.

  - "endAuth": method called when session is validated (after cookie build)

  - "authCancel": method called when user click on "cancel" during auth process

  - "forAuthUser": method called for already authenticated users

  - "beforeLogout": method called before logout

  **Note**: methods inserted so must return a PE\_\* constant. See Lemonldap::NG::Portal::Main::Constants.

Advanced entry points

These entry points are not stored in `"$req->step"` but launched on the fly:

- "afterSub": hash ref that give methods to call after given main method is called. Example:

  ```
    use constant afterSub => {
        getUser => 'mysub',
    }
    sub mysub {
        my ( $self ,$req ) = @_;
        # Do something
        return PE_OK;
    }
  ```

- "aroundSub": hash ref that give methods to call instead of given main method. Example:

  ```
    use constant aroundSub => {
        getUser => 'mysub',
    };
    sub mysub {
        my ( $self, $sub, $req ) = @_;
        # Do something before
        my $ret = $sub->($req);
        # Do something after
        return $ret;
    }
  ```

  Do not launch "getUser" but use the given `$sub`. This permits multiple plugins to use "aroundSub" in the same time.

- "hook": hash ref that gives methods to call when a hook is triggered in the LemonLDAP::NG code. Example:

  ```
    use constant hook => {
        oidcGenerateIDToken          => 'addClaimToIDToken'
    };
    sub addClaimToIDToken {
      my ( $self, $req, $payload, $rp ) = @_;
      $payload->{"id_token_hook"} = 1;
      return PE_OK;
    }
  ```

*Registering new entrypoints*

Use the `"addEntryPoint"` method to register a new entrypoint for future plugin loads. This can be useful if you would like to extend your plugin with other plugins, or interact with existing LemonLDAP::NG services in some way.

`"addEntryPoint"` takes a hash of options, for example:

```
        $self->addEntryPoint(
            isa      => "My::Base::Class",
            callback => sub {
                my ($plugin) = @_;
                $self->do_domething_with($plugin);
            }
        );
```

- "can": trigger the entry point when the newly loaded plugin has a given method

  - "does": trigger the entry point when the newly loaded plugin consumes a given role

  - "isa": trigger the entry point when the newly loaded plugin extends a given class

  - "callback": when triggered, run the given code reference, with the new plugin instance as first argument, and optional extra arguments

  - "service" and "method": when triggered, run the given method of the given portal service, with the new plugin instance as first argument, and optional extra arguments

  - "args": optional array reference of extra arguments to pass to the callback or service

  ## LOGGING

Logging is provided by `$self`-\>logger and `$self`-\>userLogger. The following rules must be applied:

- logger-\>debug: technical debugging messages

  - logger-\>info: simple technical information

  - logger-\>notice: technical information that could interest administrators

  - logger-\>warn: technical warning

  - logger-\>error: error that must be reported to administrator

  - userLogger-\>info: simple information about user's action

  - userLogger-\>notice: information that may be registered (auth success,...)

  - userLogger-\>warn: bad action of a user (auth failure). Auth/Combination transform it to "info" when another authentication scheme is available

  - userLogger-\>error: bad action of a user that must be reported, (even if another backend is available with Combination)

  ## SEE ALSO

\<http://lemonldap-ng.org\>

### OTHER POD FILES

- Writing an authentication module: Lemonldap::NG::Portal::Auth

  - Writing a UserDB module: Lemonldap::NG::Portal::UserDB

  - Writing a second factor module: Lemonldap::NG::Portal::Main::SecondFactor

  - Writing an issuer module: Lemonldap::NG::Portal::Main::Issuer

  - Writing another plugin: Lemonldap::NG::Portal::Main::Plugin

  - Request object: Lemonldap::NG::Portal::Main::Request

  - Adding parameters in the manager: Lemonldap::NG::Manager::Build

  ## AUTHORS

- LemonLDAP::NG team \<http://lemonldap-ng.org/team\>

  ## BUG REPORT

Use OW2 system to report bug or ask for features: \<https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/issues\>

## DOWNLOAD

Lemonldap::NG is available at \<https://lemonldap-ng.org/download\>

## COPYRIGHT AND LICENSE

See COPYING file for details.

This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program.  If not, see \<http://www.gnu.org/licenses/\>.
