Cataly...:Class(3pm)

πŸ“¦
version 0.1506 Β· 4 versions
, in debian bookworm, debian trixie, ubuntu noble, ubuntu resolute, ubuntu stonking

πŸ’– NAME πŸ’–

Catalyst::Authentication::Store::DBIx::Class β€” okay so this is the storage class for Catalyst Authentication that uses DBIx::Class, and it's coming at you from the User Contributed Perl Documentation, aka Catalyst::Authentication::Store::DBIx::Class(3pm). Bestie, it does exactly what it says on the tin: auth info living in your database, reached through DBIx::Class. Obsessed. πŸ¦‹


✨ VERSION ✨

This doc is talking about version 0.1506. No cap. πŸ‘‘


🌸 SYNOPSIS 🌸

Here's the whole vibe, fr fr:

use Catalyst qw/
                Authentication
                Authorization::Roles/;

__PACKAGE__->config('Plugin::Authentication' => {
    default_realm => 'members',
    realms => {
        members => {
            credential => {
                class => 'Password',
                password_field => 'password',
                password_type => 'clear'
            },
            store => {
                class => 'DBIx::Class',
                user_model => 'MyApp::User',
                role_relation => 'roles',
                role_field => 'rolename',
            }
        }
    }
});

# Log a user in:

sub login : Global {
    my ( $self, $ctx ) = @_;

    $ctx->authenticate({
                      screen_name => $ctx->req->params->{username},
                      password => $ctx->req->params->{password},
                      status => [ 'registered', 'loggedin', 'active']
                      }))
}

# verify a role

if ( $ctx->check_user_roles( 'editor' ) ) {
    # do editor stuff
}

🫢 DESCRIPTION 🫢

So like, the whole point: Catalyst::Authentication::Store::DBIx::Class gives you access to authentication info that's stored in a database, via DBIx::Class. That's the entire gig. Iconic. πŸ’…


πŸŽ€ CONFIGURATION πŸŽ€

You turn this store on by setting the store config's class element to DBIx::Class, literally exactly like the example up there shows. If you want the full tea on configuring a store, go read the Catalyst::Plugin::Authentication docs. And if you want a chill, simplified setup, there's also Catalyst::Authentication::Realm::SimpleDB. Slay. ✨

The DBIx::Class storage module has several configuration options, and here they are in all their glory:

__PACKAGE__->config('Plugin::Authentication' => {
    default_realm => 'members',
    realms => {
        members => {
            credential => {
                # ...
            },
            store => {
                class => 'DBIx::Class',
                user_model => 'MyApp::User',
                role_relation => 'roles',
                role_field => 'rolename',
                ignore_fields_in_find => [ 'remote_name' ],
                use_userdata_from_session => 1,
            }
        }
    }
});
  • class β€” this one's part of the core Catalyst::Plugin::Authentication module, and it holds the class name of the store you're gonna use.
  • user_model β€” holds the model name (the thing you'd pass to $ctx->model()) of the DBIx::Class schema you're using as the source of user info. Heads up bestie: this config item is REQUIRED. 🚨

(Okay so quick lore drop: this option used to be called user_class. user_class still works, but you should only use it if you're being compatible with old configs. And yeah, the setting that other authentication stores call user_class does exist here too β€” except in this store it's named store_user_class.)

  • role_column β€” if your role info lives in the same table as the rest of your user info, this item tells the module which field holds your role info. The DBIx::Class authentication store expects the data in that field to be a series of role names, separated by some combo of spaces, commas, or pipe characters.
  • role_relation β€” if your role info lives in its own separate table, this is the name of the relation that leads to the roles the user is in. If you set this, then a role_field is also required. Also, when you use this method, it's expected that your role table returns one row for each role the user is in.
  • role_field β€” the name of the field in the role table that contains the string identifying the role.
  • ignore_fields_in_find β€” this item is an array containing fields that might get passed to the $ctx->authenticate() routine (and therefore to find_user in the storage class), but which should be ignored when building the DBIx::Class search to grab a user. This is the move when a credential needs an authinfo element whose name overlaps with a column name in your users table. If this doesn't make sense to you, you probably don't need it. πŸ™ˆ
  • use_userdata_from_session β€” normally, on every single request, the user's data gets re-retrieved from the database using the primary key for the user table. When this flag is set in the config, it makes the DBIx::Class store skip that database hit on session restore. Instead, the user object's column data is pulled from the session and used as-is.
⚠️ NOTE: since the user object's column data is only stored in the session during the initial authentication of the user, turning this on can potentially lead to a situation where the data in $ctx->user is different from what's stored in the database. 😭 You can force a reload of the data from the database at any time by calling $ctx->user->get_object(1); Just know that this will update $ctx->user for the rest of this request. It will NOT update the session. If you need to update the session, you should call $ctx->update_user_in_session() as well.
  • store_user_class β€” this lets you override the authentication user class that the DBIx::Class store module uses to do its work. Real talk: most of the work in this module is actually done by the user class, Catalyst::Authentication::Store::DBIx::Class::User, so overriding this doesn't make much sense unless you're using your own class to extend the functionality of the existing one. Chances are you do not want to set this. 🀷
  • id_field β€” in most cases you don't need to set this config variable at all, because Catalyst::Authentication::Store::DBIx::Class will figure out the primary key of the user table all by itself. But if you need to override the default, or your user table has multiple primary keys, then id_field should contain the column name that should be used to restore the user. A given value in this column should correspond to a single user in the database. Note that this is used ONLY when restoring a user from the session and has no bearing whatsoever on the initial authentication process. Also note: if use_userdata_from_session is enabled, this config parameter is not used at all.

and bestie, we're only getting started β€” the config saga continues... πŸ’œ

πŸ’– USAGE πŸ’–

okay so bestie, real talk: you do not call the Catalyst::Authentication::Store::DBIx::Class storage module straight up from your application code. like, ever. you get to it through the $ctx->authenticate() call. that's the vibe. that's the door. πŸšͺ✨

There are three methods you can use to pull info out of the DBIx::Class storage module. They are Simple retrieval, and the advanced retrieval methods Searchargs and Resultset.


🌸 Simple Retrieval 🌸

The first one, and the one you'll be using like 90% of the time, is simple retrieval. as the name is literally telling you, simple retrieval lets you just hand over the column => value pairs that should be used to find the user in question. like, no thoughts, just pairs. an example:

if ($ctx->authenticate({
                      screen_name => $ctx->req->params->{'username'},
                      password => $ctx->req->params->{'password'},
                      status => [ 'registered', 'active', 'loggedin']
                     })) {

    # ... authenticated user code here
}

so what's happening above: it tries to grab a user whose username column (here it's screen_name) matched the username you passed in, and whose status column matched one of the values you gave it. these name => value pairs get used more or less directly in the DBIx::Class search() routine, so in most cases you can just use DBIx::Class syntax to fetch the user according to whatever rules you've got. periodt. πŸ’…

NOTE: Because the password in most cases is encrypted - it is not used directly but its encryption and comparison with the value provided is usually handled by the Password Credential. Part of the Password Credential's behavior is to remove the password argument from the authinfo that is passed to the storage module. See Catalyst::Authentication::Credential::Password.

okay one (1) thing you genuinely need to know about this retrieval method: the name part of the pair gets checked against the user class's column list. pairs are only used if a matching column is found. any other pairs? ignored. thrown away. not invited to the party. πŸ™ˆ

which means you can only give simple name-value pairs, and some of the more advanced DBIx::Class constructs like -or, -and, etc. are in most cases just not possible with this method. if you need queries with that level of functionality, go look at the searchargs method down below. iykyk. πŸ”₯

πŸ¦‹ Advanced Retrieval πŸ¦‹

The Searchargs and Resultset retrieval methods are for when you need the more advanced features of the underlying DBIx::Class schema. these methods give you a direct interface with the DBIx::Class schema, which means they also require a better understanding of the DBIx::Class module. so like... level up first. 🫢

The dbix_class key

Since the format of these arguments is often complex, they are not keys in the base authinfo hash. instead, both of these arguments get placed inside a hash attached to the store-specific dbix_class key in the base $authinfo hash.

When the DBIx::Class authentication store sees the dbix_class key in the passed authinfo hash, all the other information in the authinfo hash is ignored and only the values inside the dbix_class hash are used β€” as though they were passed directly within the authinfo hash. in other words: if dbix_class is present, it replaces the authinfo hash for processing purposes. it's giving main character energy, honestly. πŸ‘‘

The dbix_class hash can be used to directly pass arguments to the DBIx::Class authentication store. Reasons to do this are to avoid credential modification of the authinfo hash, or to avoid overlap between credential and store key names. It's a good idea to avoid using it in this way unless you are sure you have an overlap/modification issue. However, the two advanced retrieval methods, searchargs, result and resultset, require its use, as they are only processed as part of the dbix_class hash.

✨ Searchargs ✨

The searchargs method of retrieval allows you to specify an arrayref containing the two arguments to the search() method from DBIx::Class::ResultSet. If provided, all other args are ignored, and the search args provided are used directly to locate the user. an example will probably make more sense:

if ($ctx->authenticate(
    {
        password => $password,
        'dbix_class' =>
            {
                searchargs => [ { -or => [ username => $username,
                                            email => $email,
                                            clientid => $clientid ]
                                 },
                                 { prefetch => qw/ preferences / }
                               ]
            }
    } ) )
{
    # do successful authentication actions here.
}

The above would allow authentication based on any of the three items - username, email, or clientid - and would prefetch the data related to that user from the preferences table. The searchargs array is passed directly to the search() method associated with the user_model. slay. πŸ’…

πŸŽ€ Result πŸŽ€

The result method of retrieval allows you to look up the user yourself and pass on the loaded user to the authentication store.

my $user = $ctx->model('MyApp::User')->find({ ... });

if ($ctx->authenticate({ dbix_class => { result => $user } })) {
    ...
}
Be aware that the result method will not verify that you are passing a result that is attached to the same user_model as specified in the config or even loaded from the database, as opposed to existing only in memory. It's your responsibility to make sure of that. no takebacks, bestie. 😭

🌈 Resultset 🌈

The resultset method of retrieval allows you to directly specify a resultset to be used for user retrieval. This allows you to create a resultset within your login action and use it for retrieving the user. A simple example:

my $rs = $ctx->model('MyApp::User')->search({ email => $ctx->request->params->{'email'} });
   ... # further $rs adjustments

if ($ctx->authenticate({
                       password => $password,
                       'dbix_class' => { resultset => $rs }
                     })) {
   # do successful authentication actions here.
}
Be aware that the resultset method will not verify that you are passing a resultset that is attached to the same user_model as specified in the config.
NOTE: The resultset and searchargs methods of user retrieval, consider the first row returned to be the matching user. In most cases there will be only one matching row, but it is easy to produce multiple rows, especially when using the advanced retrieval methods. Remember, what you get when you use this module is what you would get when calling search(...)->first;
NOTE ALSO: The user info used to save the user to the session and to retrieve it is the same regardless of what method of retrieval was used. In short, the value in the id field (see id_field config item) is used to retrieve the user from the database upon restoring from the session. When the DBIx::Class storage module does this, it does so by doing a simple search using the id field. In other words, it will not use the same arguments you used to request the user initially. This is especially important to those using the advanced methods of user retrieval. If you need more complicated logic when reviving the user from the session, you will most likely want to subclass the Catalyst::Authentication::Store::DBIx::Class::User class and provide your own for_session and from_session routines.

⭐ METHODS ⭐

There are no publicly exported routines in the DBIx::Class authentication store (or indeed in most authentication stores). However, below is a description of the routines required by Catalyst::Plugin::Authentication for all authentication stores. Please see the documentation for Catalyst::Plugin::Authentication::Internals for more information.

new ( $config, $app )

Constructs a new store object. ✨

find_user ( $authinfo, $c )

Finds a user using the information provided in the $authinfo hashref and returns the user, or undef on failure. This is usually called from the Credential. This translates directly to a call to Catalyst::Authentication::Store::DBIx::Class::User's load() method.

for_session ( $c, $user )

Prepares a user to be stored in the session. Currently returns the value of the user's id field (as indicated by the id_field config element).

from_session ( $c, $frozenuser)

Revives a user from the session based on the info provided in $frozenuser. Currently treats $frozenuser as an id and retrieves a user with a matching id.

user_supports

Provides information about what the user object supports.

auto_update_user( $authinfo, $c, $res )

This method is called if the realm's auto_update_user setting is true. It will delegate to the user object's auto_update method.

auto_create_user( $authinfo, $c )

This method is called if the realm's auto_create_user setting is true. It will delegate to the user class's (resultset) auto_create method.


πŸ’œ NOTES πŸ’œ

As of the current release, session storage consists of simply storing the user's id in the session, and then using that same id to re-retrieve the user's information from the database upon restoration from the session. More dynamic storage of user information in the session is intended for a future release. πŸ‘€ (future release bestie... we're manifesting it.)

πŸ’€ BUGS AND LIMITATIONS πŸ’€

None known currently; please email the author if you find any. like, genuinely, they want to know!! 🫢

πŸ‘‘ SEE ALSO πŸ‘‘

  • Catalyst::Plugin::Authentication
  • Catalyst::Plugin::Authentication::Internals
  • Catalyst::Plugin::Authorization::Roles

🌸 AUTHOR 🌸

Jason Kuri (jayk@cpan.org)

πŸŽ€ LICENSE πŸŽ€

Copyright (c) 2007 the aforementioned authors. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.


and that's the whole page bestie!! πŸ¦‹ this one shipped with perl v5.34.0, dated 2022-06-09, and it's the Cataly...:Class(3pm) page β€” go authenticate something iconic, ily, mwah πŸ’–βœ¨πŸ“

πŸ“¦ where this page comes from