Adding new account properties

Just as you can spontaneously introduce new configuration settings you can spontaneously introduce new properties as well.

Note: You should not create new options for existing properties. For example, if the server-manager can only set three possible values, you should not invent a fourth one. Use another property and raise a bug to suggest the required changes.

For example, let's say that your application needs a concept of cell phone number stored for each user account. This is not a standard property in the SME Server. Your application can simply choose a name for the new property, e.g. CellNumber, and immediately start reading and writing that property for the various users - as though the property had always existed.

If you read from a non-existant property, an empty string is returned for shell scripts and the undef value is returned when using the Perl interfaces. If you write to a non-existent property, it is spontaneously created in the accounts database.

Here is an example of a user interface screen which allows you to edit cell phone numbers for each user account. As before, the form descriptions goes in /etc/e-smith/web/functions/cellnumbers :

#!/usr/bin/perl -wT
# vim: ft=xml ts=4 sw=4 et:
#----------------------------------------------------------------------
# heading     : Collaboration
# description : Cell numbers (fm)
# navigation  : 3000 3150
#----------------------------------------------------------------------
use strict;
use esmith::TestUtils;
use esmith::FormMagick::Panel::cellnumbers;

my $fm = esmith::FormMagick::Panel::cellnumbers->new();

$fm->display();

__DATA__
<form title="FORM_TITLE" 
    header="/etc/e-smith/web/common/head.tmpl" 
    footer="/etc/e-smith/web/common/foot.tmpl">

    <page name="First" pre-event="print_status_message()">

        <description>FORM_DESCRIPTION</description>

        <subroutine src="print_cellnumbers_table()" />
    </page>

    <page name="CELLNUMBERS_PAGE_MODIFY"
            pre-event="turn_off_buttons()"
            post-event="modify_cellnumber()" >

        <description>MODIFY_TITLE</description>

        <field type="literal" id="User" >
            <label>LABEL_USER</label>
        </field>

        <field type="literal" id="FullName">
            <label>LABEL_FULLNAME</label>
        </field>

        <field type="text" id="CellNumber">
            <label>LABEL_CELLNUMBER</label>
        </field>

        <subroutine src="print_button('SAVE')" />
    </page>
</form>

And the form implementation goes in /usr/lib/perl5/site_perl/esmith/FormMagick/Panels/cellnumbers.pm :

#!/usr/bin/perl -w 
package    esmith::FormMagick::Panel::cellnumbers;

use strict;

use esmith::FormMagick;
use esmith::AccountsDB;
use esmith::ConfigDB;

use Exporter;
use Carp qw(verbose);

use HTML::Tabulate;

our @ISA = qw(esmith::FormMagick Exporter);

our @EXPORT = qw();

our $db = esmith::ConfigDB->open();
our $adb = esmith::AccountsDB->open();

sub new 
{
    shift;
    my $self = esmith::FormMagick->new();
    $self->{calling_package} = (caller)[0];
    bless $self;
    return $self;
}

sub print_cellnumbers_table
{
    my $self = shift;
    my $q = $self->{cgi};

    my $cellnumbers_table =
    {
       title => $self->localise('CURRENT_LIST_OF_CELLNUMBERS'),
       
       stripe => '#D4D0C8',

       fields => [ qw(User FullName CellNumber Modify) ],

       labels => 1,

       field_attr => {
                       User => { label => $self->localise('USER_LABEL') },

                       FullName => { label => $self->localise('FULLNAME_LABEL') },

                       CellNumber => { label => $self->localise('CELLNUMBER_LABEL') },

                       Modify => { 
                                   label => $self->localise('MODIFY'),
                                   link => \&modify_link },
                                 }
           };

    my @data = ();

    my $modify = $self->localise('MODIFY');

    for my $user ($adb->users)
    {
        push @data, 
            { 
              User => $user->key,

              FullName => $user->prop('FirstName') . " " . 
                          $user->prop('LastName'),

              CellNumber => $user->prop('CellNumber') || '',

              Modify => $modify,
            }
    }

    my $t = HTML::Tabulate->new($cellnumbers_table);

    $t->render(\@data, $cellnumbers_table);
}

sub modify_link
{
    my ($data_item, $row, $field) = @_;

    return "cellnumbers?" . 
            join("&", 
                "page=0",
                "page_stack=",
                "Next=Next",
                "User="     . $row->{User},
                "FullName=" . $row->{FullName},
                "CellNumber=" . $row->{CellNumber},
                "wherenext=CELLNUMBERS_PAGE_MODIFY");
}

sub modify_cellnumber
{
    my $self = shift;
    my $q = $self->{cgi};

    my $user = $adb->get( $q->param('User') );

    $user->set_prop('CellNumber', $q->param('CellNumber'));

    return $self->success('SUCCESSFULLY_MODIFIED');
}

1;

Save the two files in the correct locations and then set the correct permissions and ownership:

cd /etc/e-smith/web/functions
chown root:admin cellnumbers
chmod 4750 cellnumbers

Then create a symbolic link to the script from the web manager cgi-bin/ directory:

cd /etc/e-smith/web/panels/manager/cgi-bin
ln -s ../../../functions/cellnumbers cellnumbers

/etc/e-smith/events/actions/navigation-conf

If you refresh the navigation bar, you will see a Cell numbers screen, which can be used to edit cell phone numbers for each user.

You could easily package this into an RPM and would just need the cellnumbers description, the cellnumbers.pm implementation and the symbolic link in the RPM. If you installed this application on any SME Server you could immediately start entering cell phone numbers for each user.