Lemonld...::Plugin(3)

πŸŽ€ NAME πŸŽ€

okay so this is the manual page for Lemonld...::Plugin(3), filed under User Contributed Perl Documentation, and it's all about Lemonldap::NG::Portal::Main::Plugin πŸ’–

It's the base class for Lemonldap::NG::Portal modules β€” plugins, authentication modules, the whole squad. everything. periodt. πŸ’…


✨ SYNOPSIS ✨

here's the vibe, bestie β€” this is what a plugin actually looks like in the wild πŸ¦‹

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 hands you so many methods so you can write Lemonldap::NG addons without wanting to scream. iconic behavior honestly πŸ‘‘

init() gets called for each and every plugin. And listen β€” if a plugin's initialization fails (aka init() returns 0), then the portal responds with a 500 status code for every single request. yeah. every one.

bestie, seriously: a 0 out of init() is a whole portal-wide situation 😭 no cap.

🧩 Writing plugins

Custom plugins can get inserted into the portal by declaring them in the lemonldap-ng.ini file, section [portal], key customPlugins:

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

And the rules? Plugins must be valid packages that are well found in @INC. that's the bar, and it's the only bar 🫢

πŸšͺ Plugin entry points

🌈 Entry point based on PATH_INFO

Plugins can declare unauthRoutes / authRoutes during initialization β€” those are =/path/info style. Methods declared this way must be declared in the plugin class. They get called with the $req argument, and $req is the HTTP request (peep Lemonldap::NG::Portal::Main::Request for that one, iykyk).

These methods must return a valid PSGI response. You can also use the sendJSONresponse() or sendHtml() methods instead (see Lemonldap::NG::Common::PSGI) β€” very handy, very slay.

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 });
}

Now β€” if you want that "protected application" behavior, you can use addAuthRouteWithRedirect. What it does is call addAuthRoute with the given arguments, and it builds an "unAuth" route that builds a redirection <em>after</em> authentication. cute, right? πŸ’œ

πŸ” Entry point in auth process

A plugin that wants to be inserted into the authentication process has to declare constants set with the method name to run. These are the entry points available to you:

  • "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 this way must return a PE_* constant. Go look at Lemonldap::NG::Portal::Main::Constants for the menu ✨

πŸͺ„ Advanced entry points

These entry points are not stored in "$req->step" β€” they're launched on the fly:

  • "afterSub" β€” hash ref that gives methods to call <em>after</em> a 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 gives methods to call <em>instead of</em> a 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. teamwork makes the dream work πŸ’–
  • "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 β€” very main character of you, honestly 🌟

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

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

And here's what those options mean:

  • "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. And the following rules must be applied β€” no freestyling here bestie:

  • 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> β€” go peek, it's giving documentation πŸ’…

πŸ“š 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

the reading list is stacked fr fr πŸ“šβœ¨


🫢 AUTHORS 🫢

LemonLDAP::NG team <http://lemonldap-ng.org/team> β€” absolute legends, we love them, no notes πŸ’œ


πŸ› BUG REPORT πŸ›

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

found a bug? don't just sit there bestie, tell the OW2 system 😀


⬇️ DOWNLOAD ⬇️

Lemonldap::NG is available at <https://lemonldap-ng.org/download> πŸŽ€


See the 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/>.


and that's the whole page, bestie! this was perl v5.42.3, dated 2026-09-24, and it's the Lemonld...::Plugin(3) manual β€” you ate that reading session, so proud of you πŸ₯ΉπŸ’– go forth and write plugins, mwah πŸŽ€βœ¨

πŸ“¦ where this page comes from