Concierge
view release on metacpan or search on metacpan
lib/Concierge/Desk/Base.pm view on Meta::CPAN
package Concierge::Desk::Base v0.9.0;
use v5.36;
our $VERSION = 'v0.9.0';
# ABSTRACT: Records-store base class for Concierge component modules
use Carp qw<croak>;
# =============================================================================
# STUB METHODS
# Each method croaks with an instructive message so subclasses cannot silently
# inherit a no-op implementation. Every subclass MUST override all of these.
# =============================================================================
sub new ($class, $config_file=undef) {
croak ref($class) || $class, " must implement new";
}
sub setup ($self, $config) {
croak ref($self), " must implement setup";
}
sub add_record ($self, $id, $data) {
croak ref($self), " must implement add_record";
}
sub remove_record ($self, $id) {
croak ref($self), " must implement remove_record";
}
sub get_record ($self, $id, @fields) {
croak ref($self), " must implement get_record";
}
sub update_record ($self, $id, $updates) {
croak ref($self), " must implement update_record";
}
sub list_records ($self, $filter='', $opts={}) {
croak ref($self), " must implement list_records";
}
1;
__END__
=head1 NAME
Concierge::Desk::Base - Records-store base class for Concierge component modules
=head1 VERSION
v0.9.0
=head1 SYNOPSIS
package Concierge::Organizations;
use parent 'Concierge::Desk::Base';
sub new ($class, $config_file) {
my $self = bless {}, $class;
$self->{config_file} = $config_file;
return $self;
}
sub setup ($self, $config) {
# Initialize storage from desk config block
# $config is the hashref for your component in concierge.conf
return { success => 1, message => 'Organizations ready' };
}
sub add_record ($self, $id, $data) {
# Persist a new organization record
# ...
return { success => 1, message => "Organization '$id' added", id => $id };
}
# ... implement remaining methods ...
1;
=head1 DESCRIPTION
C<Concierge::Desk::Base> is an abstract base class for records-store components
that integrate with Concierge desks. It documents the method contract that
Concierge expects from any additional component -- such as
C<Concierge::Organizations>, C<Concierge::Assets>, or similar -- and provides
stub implementations that die informatively if a subclass omits a required
method.
C<Concierge::Desk::Base> does B<not> depend on any of the identity core modules
(L<Concierge::Auth>, L<Concierge::Sessions>, L<Concierge::Users>) and does
not need to be used alongside them. It is purely a contract-documentation
and safety-net class.
lib/Concierge/Desk/Base.pm view on Meta::CPAN
$desk_config->{organizations_config}{config_file}
);
$orgs->setup($desk_config->{organizations_config});
$c->{organizations} = $orgs;
Alternatively, a future version of Concierge may provide a hook point for
additional components. See the EXTENSIBILITY section in L<Concierge> for
the current recommended approach.
=head1 SUBCLASSING
A minimal subclass skeleton:
package Concierge::Organizations;
use v5.36;
use parent 'Concierge::Desk::Base';
use Carp qw<croak>;
our $VERSION = 'v0.1.0';
sub new ($class, $config_file=undef) {
bless { config_file => $config_file, records => {} }, $class;
}
sub setup ($self, $config) {
# $config comes from the desk's concierge.conf
$self->{storage_path} = $config->{storage_path}
or return { success => 0, message => 'storage_path required' };
# ... initialize backend ...
return { success => 1, message => 'Organizations initialized' };
}
sub add_record ($self, $id, $data) {
return { success => 0, message => 'id is required' }
unless defined $id && length $id;
return { success => 0, message => "Record '$id' already exists" }
if exists $self->{records}{$id};
$self->{records}{$id} = $data;
return { success => 1, message => "Organization '$id' added", id => $id };
}
sub remove_record ($self, $id) {
return { success => 0, message => "Record '$id' not found" }
unless exists $self->{records}{$id};
delete $self->{records}{$id};
return { success => 1, message => "Organization '$id' removed" };
}
sub get_record ($self, $id, @fields) {
return { success => 0, message => "Record '$id' not found" }
unless exists $self->{records}{$id};
my $data = $self->{records}{$id};
if (@fields) {
my %selected = map { $_ => $data->{$_} }
grep { exists $data->{$_} } @fields;
return { success => 1, record => \%selected };
}
return { success => 1, record => $data };
}
sub update_record ($self, $id, $updates) {
return { success => 0, message => "Record '$id' not found" }
unless exists $self->{records}{$id};
$self->{records}{$id} = { %{$self->{records}{$id}}, %$updates };
return { success => 1, message => "Organization '$id' updated" };
}
sub list_records ($self, $filter='', $opts={}) {
my @ids = sort keys %{$self->{records}};
return { success => 1, ids => \@ids, count => scalar @ids }
unless $opts->{include_data};
my %records = map { $_ => $self->{records}{$_} } @ids;
return { success => 1, ids => \@ids, records => \%records, count => scalar @ids };
}
1;
=head1 SEE ALSO
L<Concierge> -- main orchestrator; see its EXTENSIBILITY section for the
component substitution and addition pattern.
L<Concierge::Desk::Setup> -- desk creation and configuration.
L<Concierge::Users> -- the identity core records-store component, which
provides a production example of a records-store component integrated with
a Concierge desk.
=head1 AUTHOR
Bruce Van Allen <bva@cruzio.com>
=head1 LICENSE
This module is free software; you can redistribute it and/or modify it
under the terms of the Artistic License 2.0.
=cut
( run in 0.958 second using v1.01-cache-2.11-cpan-7fcb06a456a )