NAME

WWW::Authentik::Diff - Compare an authentik representation with the wanted state, without I/O

VERSION

version 0.001

SYNOPSIS

my $changes = WWW::Authentik::Diff->changes( $current, { name => 'probe', attributes => { a => 'b' } } );
return unless %$changes;                        # nothing to do
my $full = WWW::Authentik::Diff->merge( $current, $wanted );

DESCRIPTION

The comparison behind every ensure_* method of WWW::Authentik::API, kept free of I/O so that Net::Async::Authentik uses the very same code.

Only the keys of the wanted state are looked at. Hashes are compared key by key, so a wanted attributes hash with one entry checks that entry and leaves the others alone; a nested hash that differs comes back merged, because authentik replaces such a hash as a whole.

Every list is compared as a multiset: authentik hands property_mappings back in its own order, and in none of the lists this client writes does the order carry meaning. Lists of hashes are compared the same way, each element as canonical JSON.

Some fields come back with values authentik filled in. "list_defaults" names them, and "with_defaults" lays them over the wanted value before the comparison, so that writing a redirect_uris entry without redirect_uri_type does not report a change on every run.

Booleans compare equal whatever their spelling: \1, a JSON true, "true" and 1 are the same value, and so are \0, a JSON false, "false" and 0. Everything else is compared as a string, so 3600 and "3600" are equal.

One asymmetry: authentik trims leading and trailing whitespace off every text field it stores, so a wanted "two lines\n" comes back as "two lines". Such a value could never be reached and ensure_* would report a change for ever, so a stored value that is exactly the trimmed form of the wanted one counts as equal. The comparison runs in that direction only: a stored value with whitespace against a wanted one without it is still a difference, which is what happens inside attributes, where authentik keeps whitespace.

list_defaults

my $defaults = WWW::Authentik::Diff->list_defaults;

The fields where authentik fills a value into every element of a list, as a hash of field name to the defaults for one element. Override it in a subclass when a later authentik version adds another.

with_defaults

my $wanted = WWW::Authentik::Diff->with_defaults( redirect_uris => \@uris );

The value with "list_defaults" laid under every element, so it can be compared with what authentik stored. Anything that is not a list of hashes comes back unchanged.

changes

my $changes = WWW::Authentik::Diff->changes( \%current, \%wanted );

The keys that have to be written to turn the current state into the wanted one, as a hash. A nested hash that differs comes back merged with its current content. The values are the ones that were asked for, not the ones the defaults were laid under. Empty when there is nothing to do.

merge

my $full = WWW::Authentik::Diff->merge( \%current, \%wanted );

The current state with the wanted keys laid over it, nested hashes merged key by key.

same

WWW::Authentik::Diff->same( $a, $b )

True when two values are the same in the sense described above.

SUPPORT

Issues

Please report bugs and feature requests on GitHub at https://github.com/Getty/p5-www-authentik/issues.

IRC

Join #kubernetes on irc.perl.org or message Getty directly.

CONTRIBUTING

Contributions are welcome! Please fork the repository and submit a pull request.

AUTHOR

Torsten Raudssus <getty@cpan.org>

COPYRIGHT AND LICENSE

This software is copyright (c) 2026 by Torsten Raudssus <torsten@raudssus.de> https://raudssus.de/.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.