Updating RT from an LDAP database

One of the needs we have here at the University of Oslo, is to keep
the information in RT up to date with the information in LDAP. To
make this happen, I wrote a small script to update the info for all
"local" RT users with information from LDAP.

It could be useful for others, so I post it here as well. The LDAP
connect and disconnect functions are available in an extention to
RT::USER on URL:http://www.usit.uio.no/it/rt/modifications.html.

#!/site/perl-5.8.6/bin/perl

Author: Petter Reinholdtsen

Date: 2005-08-08

License: GPL

Update RT user information with information from an LDAP database.

use lib ("/site/rt3/local/lib", “/site/rt3/lib”);
use strict;
use warnings;

use Getopt::Std;

use Net::LDAP qw(LDAP_SUCCESS LDAP_SERVER_DOWN LDAP_OPERATIONS_ERROR);
use Net::LDAP::Util qw (ldap_error_name);
use RT::Interface::CLI qw(CleanEnv);
use RT::User;

my %opts;

getopts(“dn”, %opts);

CleanEnv();
RT::LoadConfig();
RT::Init();

my %system_users = (‘root’ => “Superuser”,
‘rt-user’ => “Internal user”,
‘Nobody’ => “No user at all”,
‘RT_System’ => “Internal user”);

Only the entries present here will be updated, no matter what the

LDAP database contain.

Not including Name to make sure users don’t suddenly change user

name because their mail address happen to point to a different user.

my @updatevalues =
qw(
EmailAddress
RealName
WorkPhone
Address1
);

How to map from LDAP to RT values for the threes being queried for

information.

my @LdapUserMap =
(
{
base => ‘cn=targets,cn=mail,dc=uio,dc=no’,
search => ‘target’,
filter => ‘(&(objectClass=mailAddr)(targetType=user))’,
scope => ‘one’,
map => {‘target’ => ‘Name’,
‘defaultMailAddress’ => ‘EmailAddress’}
},
{
base => ‘cn=people,dc=uio,dc=no’,
search => ‘uid’,
filter => ‘(objectClass=person)’,
scope => ‘’,
map => {‘cn’ => ‘RealName’,
‘telephoneNumber’ => ‘WorkPhone’,
‘street’ => ‘Address1’}
},
{
base => ‘cn=users,cn=system,dc=uio,dc=no’,
search => ‘uid’,
filter => ‘(objectclass=posixAccount)’,
scope => ‘’,
map => {‘cn’ => ‘RealName’,
‘telephoneNumber’ => ‘WorkPhone’},
}
);

my $ldaphandle = RT::User::LdapConnect();

Loop over all RT users

my $users = new RT::Users($RT::SystemUser);
while (my $user = $users->Next) {
my $username = $user->Name;
next if ($system_users{$username});
next if ($username =~ m/@/); # Ignore external users

my %current;
for my $key (@updatevalues) {
    $current{$key} = $user->$key;
}

my ($found, %userinfo) =
    LookupExternalUserInfoByName($user->Name);

# XXX LDAP lookup of RealName is not implemented in
# LookupExternalUserInfo() [pere 2005-08-08]
if (!$found) {
    my $msg = "User '$username' is missing in LDAP";
    $RT::Logger->info("$msg"); print "$msg\n" if $opts{'d'};
    # XXX Deleted user?  Should it be converted to an external
    # user, by replacing the username with the mail address?
    # Not sure.  Ignore it for now. [pere 2005-08-08]
    next;
}
for my $key (sort keys %userinfo) {
    #print "  $key - '$userinfo{$key}' cmp '$current{$key}'\n" if $opts{'d'};
    if (exists $current{$key} && $current{$key} ne $userinfo{$key}) {
        my $dryrun = $opts{'n'} ? " (dryrun)" : "";

        my $msg = "Updating $key for user '$username' from LDAP: ".
            "'$current{$key}' to '$userinfo{$key}'$dryrun";
        $RT::Logger->info("$msg"); print "$msg\n" if $opts{'d'};

        my $method = "Set$key";
        my ($retval, $retmsg) = $user->$method($userinfo{$key})
            unless $opts{'n'};
    }
}

}

RT::User::LdapDisconnect($ldaphandle);

exit 0;

=head2 LookupExternalUserInfoByName

Look up a username in several subtrees of LDAP, and pass the
information found back to the caller.

=cut

sub LookupExternalUserInfoByName {
my ($name) = @_;

# Wash the name to avoid surprises when searching for it.
if ($name =~ m/^([a-z0-9_.-]+)$/) {
    $name = $1;
} else {
    my $msg = "LookupExternalUserInfoByName: ".
        "Illegal username '$name' rejected.";
    $RT::Logger->debug($msg); print "$msg\n" if $opts{'d'};
    return (0, undef);
}

my %userinfo;
my $found = 0;
for my $ldaptree (@LdapUserMap) {
  retry:
    my @attrs = keys %{$ldaptree->{'map'}};
    my $filter = "(&($ldaptree->{search}=$name)$ldaptree->{filter})";
    my $mesg = $ldaphandle->search(base   => $ldaptree->{base},
                                   filter => $filter,
                                   attrs  => [@attrs]);

    # Handle timeouts
    if (($mesg->code == LDAP_SERVER_DOWN) or
        ($mesg->code == LDAP_OPERATIONS_ERROR)) {
        my $msg = "LookupExternalUserInfoByName: ".
            "Connection time out.  Reconnecting";
        $RT::Logger->debug($msg); print "$msg\n" if $opts{'d'};
        $ldaphandle = RT::User::LdapConnect();
        goto retry if ($ldaphandle);
        $msg = "LookupExternalUserInfoByName: ".
            "Reconnect failed.  Giving up!";
        $RT::Logger->debug($msg); print "$msg\n" if $opts{'d'};
        last;
    }

    if ($mesg->code == LDAP_SUCCESS) {
        if (1 == $mesg->count) {
            # Got working result.  Use it.
            while( my $entry = $mesg->shift_entry) {
                foreach my $attr (keys %{$ldaptree->{'map'}}) {
                    foreach my $value ($entry->get_value($attr)) {
                        # Let Perl know this is UTF-8
                        $value = Encode::decode_utf8( $value );
                        $userinfo{$ldaptree->{'map'}{$attr}} = $value;
                    }
                }
            }
            $found = 1;
        } elsif (1 < $mesg->count) {
            my $msg = "LookupExternalUserInfoByName: ".
                "Searching for $filter returned $mesg->count entries.  ".
                "It should return only one.";
            $RT::Logger->debug($msg); print "$msg\n" if $opts{'d'};
        } # else count == 0 -> no hit, nothing to report
    } else {
        my $msg = "LookupExternalUserInfoByName: ".
            "Could not search for $filter: " .
            "retval=" . $mesg->code . " " . ldap_error_name($mesg->code);
        $RT::Logger->debug($msg); print "$msg\n" if $opts{'d'};
    }
}
return ($found, %userinfo)

}

We just migrated our RT system from an old installation on an old server to
a new one that will use LDAP to create users.

The issue is that we already have a good number of users on the old system,
and would like to keep them around.

I realize the most straight forward decision is to simply rename the users
(and change their email addresses), and when they are recreated when a user
first logs in, just shred the old accounts and replace the relations to the
new ones.

I then got to thinking that there must be a way to update the users in RT
through LDAP, not only for this reason but for regular maintenance.

Anyway, I was googling around and found this old script from 2005
http://lists.bestpractical.com/pipermail/rt-devel/2005-August/007451.html
As it is 5 years old, it doesn’t work well. I’m no RT developer, so it’d
take a while to figure out what needs to be changed, so my question is,
would anyone out there be able to update this script to work with a more
current version of RT (as of emailing, 3.8.8). There really only is one
error, so I’m hoping it wouldn’t take too long.

The one warning and one critical error I get are:

[Thu Jul 8 19:00:13 2010] [warning]: Use of inherited AUTOLOAD for

non-method RT::User::LdapConnect() is deprecated at updateldap.pm line 70.
(updateldap.pm:70)

[Thu Jul 8 19:00:13 2010] [crit]: Can’t call method “_Accessible” on an

undefined value at /usr/local/share/perl/5.10.0/DBIx/SearchBuilder/Record.pm
line 423. (/opt/rt3/lib/RT.pm:382)

Can’t call method “_Accessible” on an undefined value at

/usr/local/share/perl/5.10.0/DBIx/SearchBuilder/Record.pm line 423.

Thanks for the help.

Jonah Hirsch

I realized that my line numbers will be different as I’ve edited the script.

Line 70: my $ldaphandle = RT::User::LdapConnect();
Jonah HirschOn Thu, Jul 8, 2010 at 12:07 PM, Jonah Hirsch crazydog115@gmail.com wrote:

We just migrated our RT system from an old installation on an old server to
a new one that will use LDAP to create users.

The issue is that we already have a good number of users on the old system,
and would like to keep them around.

I realize the most straight forward decision is to simply rename the users
(and change their email addresses), and when they are recreated when a user
first logs in, just shred the old accounts and replace the relations to the
new ones.

I then got to thinking that there must be a way to update the users in RT
through LDAP, not only for this reason but for regular maintenance.

Anyway, I was googling around and found this old script from 2005
[Rt-devel] Updating RT from an LDAP database
As it is 5 years old, it doesn’t work well. I’m no RT developer, so it’d
take a while to figure out what needs to be changed, so my question is,
would anyone out there be able to update this script to work with a more
current version of RT (as of emailing, 3.8.8). There really only is one
error, so I’m hoping it wouldn’t take too long.

The one warning and one critical error I get are:

[Thu Jul 8 19:00:13 2010] [warning]: Use of inherited AUTOLOAD for

non-method RT::User::LdapConnect() is deprecated at updateldap.pm line
70. (updateldap.pm:70)

[Thu Jul 8 19:00:13 2010] [crit]: Can’t call method “_Accessible” on an

undefined value at /usr/local/share/perl/5.10.0/DBIx/SearchBuilder/Record.pm
line 423. (/opt/rt3/lib/RT.pm:382)

Can’t call method “_Accessible” on an undefined value at

/usr/local/share/perl/5.10.0/DBIx/SearchBuilder/Record.pm line 423.

Thanks for the help.

Jonah Hirsch

I realized that my line numbers will be different as I’ve edited the script.
Line 70: my $ldaphandle = RT::User::LdapConnect();

You seem to have missed the second paragraph which explains that you
also need another extension they wrote

Have you looked into

to see if it will do the syncing you want?

-kevin

Yeah, I got that installed, but I’m still getting those same errors.
Jonah HirschOn Thu, Jul 8, 2010 at 3:07 PM, Kevin Falcone falcone@bestpractical.comwrote:

On Thu, Jul 08, 2010 at 12:10:33PM -0700, Jonah Hirsch wrote:

I realized that my line numbers will be different as I’ve edited the
script.
Line 70: my $ldaphandle = RT::User::LdapConnect();

You seem to have missed the second paragraph which explains that you
also need another extension they wrote

Have you looked into
RT-Extension-LDAPImport-0.36 - Import Users from an LDAP store - metacpan.org
to see if it will do the syncing you want?

-kevin

On Thu, Jul 8, 2010 at 12:07 PM, Jonah Hirsch <[1] crazydog115@gmail.com> wrote:

 We just migrated our RT system from an old installation on an old

server to a new one that

 will use LDAP to create users.
 The issue is that we already have a good number of users on the old

system, and would like

 to keep them around.
 I realize the most straight forward decision is to simply rename the

users (and change their

 email addresses), and when they are recreated when a user first logs

in, just shred the old

 accounts and replace the relations to the new ones.
 I then got to thinking that there must be a way to update the users

in RT through LDAP, not

 only for this reason but for regular maintenance.
 Anyway, I was googling around and found this old script from 2005
 [2]

[Rt-devel] Updating RT from an LDAP database

 As it is 5 years old, it doesn't work well. I'm no RT developer, so

it’d take a while to

 figure out what needs to be changed, so my question is, would anyone

out there be able to

 update this script to work with a more current version of RT (as of

emailing, 3.8.8). There

 really only is one error, so I'm hoping it wouldn't take too long.
 The one warning and one critical error I get are:

   [Thu Jul 8 19:00:13 2010] [warning]: Use of inherited AUTOLOAD for

non-method

   RT::User::LdapConnect() is deprecated at [3]updateldap.pm line
  1. ([4]updateldap.pm:70)
   [Thu Jul 8 19:00:13 2010] [crit]: Can't call method "_Accessible"

on an undefined value at

   /usr/local/share/perl/5.10.0/DBIx/SearchBuilder/Record.pm line
   (/opt/rt3/lib/RT.pm:382)

   Can't call method "_Accessible" on an undefined value at
   /usr/local/share/perl/5.10.0/DBIx/SearchBuilder/Record.pm line
 Thanks for the help.
 Jonah Hirsch
 -----------------------

References

Visible links

  1. mailto:crazydog115@gmail.com

[Rt-devel] Updating RT from an LDAP database

  1. http://updateldap.pm/
  2. http://updateldap.pm:70/

List info:
The rt-devel Archives


List info:
The rt-devel Archives

I need to stop reading things so fast. My brain put “other extension”
together with the LDAPImport extension.

Anyway, I tried the LDAPImport extension, but I didn’t see an easy way to
get it to go through every user in RT and update their info.
Jonah HirschOn Thu, Jul 8, 2010 at 3:11 PM, Jonah Hirsch crazydog115@gmail.com wrote:

Yeah, I got that installed, but I’m still getting those same errors.
Jonah Hirsch

On Thu, Jul 8, 2010 at 3:07 PM, Kevin Falcone falcone@bestpractical.comwrote:

On Thu, Jul 08, 2010 at 12:10:33PM -0700, Jonah Hirsch wrote:

I realized that my line numbers will be different as I’ve edited the
script.
Line 70: my $ldaphandle = RT::User::LdapConnect();

You seem to have missed the second paragraph which explains that you
also need another extension they wrote

Have you looked into
RT-Extension-LDAPImport-0.36 - Import Users from an LDAP store - metacpan.org
to see if it will do the syncing you want?

-kevin

On Thu, Jul 8, 2010 at 12:07 PM, Jonah Hirsch <[1] crazydog115@gmail.com> wrote:

 We just migrated our RT system from an old installation on an old

server to a new one that

 will use LDAP to create users.
 The issue is that we already have a good number of users on the old

system, and would like

 to keep them around.
 I realize the most straight forward decision is to simply rename

the users (and change their

 email addresses), and when they are recreated when a user first

logs in, just shred the old

 accounts and replace the relations to the new ones.
 I then got to thinking that there must be a way to update the users

in RT through LDAP, not

 only for this reason but for regular maintenance.
 Anyway, I was googling around and found this old script from 2005
 [2]

[Rt-devel] Updating RT from an LDAP database

 As it is 5 years old, it doesn't work well. I'm no RT developer, so

it’d take a while to

 figure out what needs to be changed, so my question is, would

anyone out there be able to

 update this script to work with a more current version of RT (as of

emailing, 3.8.8). There

 really only is one error, so I'm hoping it wouldn't take too long.
 The one warning and one critical error I get are:

   [Thu Jul 8 19:00:13 2010] [warning]: Use of inherited AUTOLOAD

for non-method

   RT::User::LdapConnect() is deprecated at [3]updateldap.pm line
  1. ([4]updateldap.pm:70)
   [Thu Jul 8 19:00:13 2010] [crit]: Can't call method "_Accessible"

on an undefined value at

   /usr/local/share/perl/5.10.0/DBIx/SearchBuilder/Record.pm line
   (/opt/rt3/lib/RT.pm:382)

   Can't call method "_Accessible" on an undefined value at
   /usr/local/share/perl/5.10.0/DBIx/SearchBuilder/Record.pm line
 Thanks for the help.
 Jonah Hirsch
 -----------------------

References

Visible links

  1. mailto:crazydog115@gmail.com

[Rt-devel] Updating RT from an LDAP database

  1. http://updateldap.pm/
  2. http://updateldap.pm:70/

List info:
The rt-devel Archives


List info:
The rt-devel Archives

And now I remember that that as that email is 5 years old, the link to the
other extension does not seem to exist anymore…(
http://www.usit.uio.no/it/rt/modifications.html) try it yourself.
Jonah HirschOn Thu, Jul 8, 2010 at 3:13 PM, Jonah Hirsch crazydog115@gmail.com wrote:

I need to stop reading things so fast. My brain put “other extension”
together with the LDAPImport extension.

Anyway, I tried the LDAPImport extension, but I didn’t see an easy way to
get it to go through every user in RT and update their info.
Jonah Hirsch

On Thu, Jul 8, 2010 at 3:11 PM, Jonah Hirsch crazydog115@gmail.comwrote:

Yeah, I got that installed, but I’m still getting those same errors.
Jonah Hirsch

On Thu, Jul 8, 2010 at 3:07 PM, Kevin Falcone falcone@bestpractical.comwrote:

On Thu, Jul 08, 2010 at 12:10:33PM -0700, Jonah Hirsch wrote:

I realized that my line numbers will be different as I’ve edited the
script.
Line 70: my $ldaphandle = RT::User::LdapConnect();

You seem to have missed the second paragraph which explains that you
also need another extension they wrote

Have you looked into
RT-Extension-LDAPImport-0.36 - Import Users from an LDAP store - metacpan.org
to see if it will do the syncing you want?

-kevin

On Thu, Jul 8, 2010 at 12:07 PM, Jonah Hirsch <[1] crazydog115@gmail.com> wrote:

 We just migrated our RT system from an old installation on an old

server to a new one that

 will use LDAP to create users.
 The issue is that we already have a good number of users on the

old system, and would like

 to keep them around.
 I realize the most straight forward decision is to simply rename

the users (and change their

 email addresses), and when they are recreated when a user first

logs in, just shred the old

 accounts and replace the relations to the new ones.
 I then got to thinking that there must be a way to update the

users in RT through LDAP, not

 only for this reason but for regular maintenance.
 Anyway, I was googling around and found this old script from 2005
 [2]

[Rt-devel] Updating RT from an LDAP database

 As it is 5 years old, it doesn't work well. I'm no RT developer,

so it’d take a while to

 figure out what needs to be changed, so my question is, would

anyone out there be able to

 update this script to work with a more current version of RT (as

of emailing, 3.8.8). There

 really only is one error, so I'm hoping it wouldn't take too long.
 The one warning and one critical error I get are:

   [Thu Jul 8 19:00:13 2010] [warning]: Use of inherited AUTOLOAD

for non-method

   RT::User::LdapConnect() is deprecated at [3]updateldap.pm line
  1. ([4]updateldap.pm:70)
   [Thu Jul 8 19:00:13 2010] [crit]: Can't call method

“_Accessible” on an undefined value at

   /usr/local/share/perl/5.10.0/DBIx/SearchBuilder/Record.pm line
   (/opt/rt3/lib/RT.pm:382)

   Can't call method "_Accessible" on an undefined value at
   /usr/local/share/perl/5.10.0/DBIx/SearchBuilder/Record.pm line
 Thanks for the help.
 Jonah Hirsch
 -----------------------

References

Visible links

  1. mailto:crazydog115@gmail.com

[Rt-devel] Updating RT from an LDAP database

  1. http://updateldap.pm/
  2. http://updateldap.pm:70/

List info:
The rt-devel Archives


List info:
The rt-devel Archives

And now I remember that that as that email is 5 years old, the link to the other extension
does not seem to exist anymore…([1]http://www.usit.uio.no/it/rt/modifications.html) try it
yourself.

I’ll note that I wrote RT-Extension-LDAPImport so I’ve never used the
script that you reference. I was attempting to point you at something
that would be a bit more modern and possibly work on a recent RT

-kevin> On Thu, Jul 8, 2010 at 3:13 PM, Jonah Hirsch <[2]crazydog115@gmail.com> wrote:

 I need to stop reading things so fast. My brain put "other extension" together with the
 LDAPImport extension.
 Anyway, I tried the LDAPImport extension, but I didn't see an *easy* way to get it to go
 through every user in RT and update their info.
 Jonah Hirsch
 -----------------------

 On Thu, Jul 8, 2010 at 3:11 PM, Jonah Hirsch <[3]crazydog115@gmail.com> wrote:

   Yeah, I got that installed, but I'm still getting those same errors.
   Jonah Hirsch
   -----------------------

   On Thu, Jul 8, 2010 at 3:07 PM, Kevin Falcone <[4]falcone@bestpractical.com> wrote:

     On Thu, Jul 08, 2010 at 12:10:33PM -0700, Jonah Hirsch wrote:
     > I realized that my line numbers will be different as I've edited the script.
     > Line 70: my $ldaphandle = RT::User::LdapConnect();

     You seem to have missed the second paragraph which explains that you
     also need another extension they wrote

     Have you looked into
     [5]http://search.cpan.org/dist/RT-Extension-LDAPImport/
     to see if it will do the syncing you want?

     -kevin
     >
     > On Thu, Jul 8, 2010 at 12:07 PM, Jonah Hirsch <[1][6]crazydog115@gmail.com> wrote:
     >
     > We just migrated our RT system from an old installation on an old server to a new one
     that
     > will use LDAP to create users.
     > The issue is that we already have a good number of users on the old system, and would
     like
     > to keep them around.
     > I realize the most straight forward decision is to simply rename the users (and change
     their
     > email addresses), and when they are recreated when a user first logs in, just shred
     the old
     > accounts and replace the relations to the new ones.
     > I then got to thinking that there must be a way to update the users in RT through
     LDAP, not
     > only for this reason but for regular maintenance.
     > Anyway, I was googling around and found this old script from 2005
     > [2][7]http://lists.bestpractical.com/pipermail/rt-devel/2005-August/007451.html
     > As it is 5 years old, it doesn't work well. I'm no RT developer, so it'd take a while
     to
     > figure out what needs to be changed, so my question is, would anyone out there be able
     to
     > update this script to work with a more current version of RT (as of emailing, 3.8.8).
     There
     > really only is one error, so I'm hoping it wouldn't take too long.
     > The one warning and one critical error I get are:
     >
     > [Thu Jul 8 19:00:13 2010] [warning]: Use of inherited AUTOLOAD for non-method
     > RT::User::LdapConnect() is deprecated at [3][8]updateldap.pm line 70.
     ([4][9]updateldap.pm:70)
     >
     > [Thu Jul 8 19:00:13 2010] [crit]: Can't call method "_Accessible" on an undefined
     value at
     > /usr/local/share/perl/5.10.0/DBIx/SearchBuilder/Record.pm line 423.
     > (/opt/rt3/lib/RT.pm:382)
     >
     > Can't call method "_Accessible" on an undefined value at
     > /usr/local/share/perl/5.10.0/DBIx/SearchBuilder/Record.pm line 423.
     >
     > Thanks for the help.
     > Jonah Hirsch
     > -----------------------
     >
     > References
     >
     > Visible links
     > 1. mailto:[10]crazydog115@gmail.com
     > 2. [11]http://lists.bestpractical.com/pipermail/rt-devel/2005-August/007451.html
     > 3. [12]http://updateldap.pm/
     > 4. [13]http://updateldap.pm:70/
     > _______________________________________________
     > List info: [14]http://lists.bestpractical.com/cgi-bin/mailman/listinfo/rt-devel

     _______________________________________________
     List info: [15]http://lists.bestpractical.com/cgi-bin/mailman/listinfo/rt-devel

References

Visible links

  1. http://www.usit.uio.no/it/rt/modifications.html
  2. mailto:crazydog115@gmail.com
  3. mailto:crazydog115@gmail.com
  4. mailto:falcone@bestpractical.com
  5. RT-Extension-LDAPImport-0.36 - Import Users from an LDAP store - metacpan.org
  6. mailto:crazydog115@gmail.com
  7. [Rt-devel] Updating RT from an LDAP database
  8. http://updateldap.pm/
  9. http://updateldap.pm:70/
  10. mailto:crazydog115@gmail.com
  11. [Rt-devel] Updating RT from an LDAP database
  12. http://updateldap.pm/
  13. http://updateldap.pm:70/
  14. The rt-devel Archives
  15. The rt-devel Archives

List info: The rt-devel Archives

And now I remember that that as that email is 5 years old, the link to
the other extension
does not seem to exist anymore…([1]
http://www.usit.uio.no/it/rt/modifications.html) try it
yourself.

I’ll note that I wrote RT-Extension-LDAPImport so I’ve never used the
script that you reference. I was attempting to point you at something
that would be a bit more modern and possibly work on a recent RT

-kevin

Did you ever merge and publish my patches, Kevin? :slight_smile:

-Rob

 > Â Â And now I remember that that as that email is 5 years old, the link to the other
 extension
 > Â Â does not seem to exist
 anymore....([1][2]http://www.usit.uio.no/it/rt/modifications.html) try it
 > Â Â yourself.

 I'll note that I wrote RT-Extension-LDAPImport so I've never used the
 script that you reference. Â I was attempting to point you at something
 that would be a bit more modern and possibly work on a recent RT

 -kevin

Did you ever merge and publish my patches, Kevin? :slight_smile:

No. Although since someone has requested development of the module,
they’ll get attention this summer

-kevin