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 )