App-MFILE-WWW

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

  'Mason::Plugin::Utf8' to the 'Development notes' section

0.010  2014-08-13 16:05 CEST
- Build.PL: update dependencies
- MANIFEST: add auth.mi

0.011  2014-08-14 09:15 CEST
- add COPYING file with text of BSD license
- WWW.pm: write some POD
- add license boilerplate to Mason components
- auth.mi: get length of username and password fields from site configuration
- tickets/: work on tickets

0.012  2014-08-14 14:58 CEST
- share/config/WWW_Config.pm: add DOCHAZKA_WWW_HOST and DOCHAZKA_WWW_PORT
- bin/dochazka-www: look into how we could allow admin to specify host/port on
  command line, yet default to values in site configuration if they are not
  specified there

0.013  2014-08-14 17:01 CEST
- fighting with web technologies

Changes  view on Meta::CPAN

- js/: first shot at employee search functionality for administrators: simple 
  form gathers a nick search key (e.g. 'ro%') which matches 'n' records,
  which can then be displayed/browsed using a clumsy set of forms -- it is 
  enough to see that:
  (a) it can be done using the simple forms, but
  (b) realistically, a new widget will be needed

0.056  2014-08-29 08:53 CEST
- js/: add 'changePassword' target
- status: changePassword works, but REST server does not allow passerbies and
  inactives to change their passwords -- need to look at that

0.057  2014-08-29 13:42 CEST
- Resource.pm: 'rest_req' now returns entire HTTP::Response object instead
  of just its 'code' property: adapt our code to handle that; AJAX calls 
  return HTTP response code _and_ message
- js/: run JSlint on all the JavaScript source files and fix all errors

0.058  2014-08-29 16:18 CEST
- css/: widen application frame by "50 pixels"
- Build.PL: require App::Dochazka version 0.164 minimum

lib/App/MFILE/WWW/Dispatch.pm  view on Meta::CPAN


=cut

sub validate_user_credentials {
    my ( $self, $body ) = @_;
    $log->debug( "Entering " . __PACKAGE__ . "::validate_user_credentials()" );

    my $r = $self->request;
    my $session = $r->{'env'}->{'psgix.session'};
    my $nick = $body->{'nam'};
    my $password = $body->{'pwd'};
    my $standalone = $meta->META_WWW_STANDALONE_MODE;

    $log->debug( "Employee $nick login attempt" );

    my ( $code, $message, $body_json );
    if ( $standalone ) {
        # check nam and pwd against MFILE_WWW_STANDALONE_CREDENTIALS_DATABASE
        my $db = $site->MFILE_WWW_STANDALONE_CREDENTIALS_DATABASE;
        $code = 401;
        $message = 'Unauthorized';
        for my $entry (@$db) {
            if ( $nick eq $entry->{'nam'} ) {
                if ( $password eq $entry->{'pwd'} ) {
                    $code = 200;
                    $message = 'OK';
                    $body_json = { payload => 
                        { 
                            emp => { nick => $nick, eid => $entry->{'eid'} },
                            priv => $entry->{'priv'} 
                        }
                    };
                }
                last;

lib/App/MFILE/WWW/Resource.pm  view on Meta::CPAN

    $r .= "testing: " . ( $testing ? 'true' : 'false' );

    $r .= '} } });';
    $r .= '</script>';
    return $r;
} 


=head2 login_status

Once the username and password are known (either from C<process_post> via the
login AJAX request generated by the login dialog, or from the site
configuration via the MFILE_WWW_BYPASS_LOGIN_DIALOG mechanism), the
C<validate_user_credentials> method is called. That method is implemented by
the derived application, so it can validate user credentials however it likes.
The C<validate_user_credentials> method is then expected to call this method -
C<login_status> - to generate a status object from the results of the user
credentials validation.

Now, C<App::MFILE::WWW> does expect the C<validate_user_credentials> method to
provide the results of user credentials validation in a peculiar format,

lib/App/MFILE/WWW/Resource.pm  view on Meta::CPAN

Algorithm: send request to REST server, get JSON response, decode it, return
it.

Takes a single _mandatory_ parameter: a LWP::UserAgent object

Optionally takes PARAMHASH:

    server => [URI OF REST SERVER]         default is 'http://0:5000'
    method => [HTTP METHOD TO USE]         default is 'GET'
    nick => [NICK FOR BASIC AUTH]          optional
    password => [PASSWORD FOR BASIC AUTH]  optional
    path => [PATH OF REST RESOURCE]        default is '/'
    req_body => [HASHREF]                  optional

Returns HASHREF containing:

    hr => HTTP::Response object (stripped of the body)
    body => [BODY OF HTTP RESPONSE, IF ANY] 

=cut

sub rest_req {
    my $self = shift;

    # process arguments
    my $ua = $self->ua();
    die "Bad user agent object" unless ref( $ua ) eq 'LWP::UserAgent';
    my %ARGS = validate( @_, {
        server =>   { type => SCALAR,  default => 'http://localhost:5000' },
        method =>   { type => SCALAR,  default => 'GET', regex => qr/^(GET|POST|PUT|DELETE)$/ },
        nick =>     { type => SCALAR,  optional => 1 },
        password => { type => SCALAR,  default => '' },
        path =>     { type => SCALAR,  default => '/' },
        req_body => { type => HASHREF, optional => 1 },
    } );
    $ARGS{'path'} =~ s/^\/*/\//;

    my $r;
    {
        no strict 'refs';
        $r = &{ $ARGS{'method'} }( $ARGS{'server'} . encode_utf8( $ARGS{'path'} ), 
                Accept => 'application/json' );
    }

    if ( $ARGS{'nick'} ) {
        $r->authorization_basic( $ARGS{'nick'}, $ARGS{'password'} );
    }

    if ( $ARGS{'method'} =~ m/^(POST|PUT)$/ ) {
        $r->header( 'Content-Type' => 'application/json' );
        if ( my $body = $ARGS{'req_body'} ) {
            my $tmpvar = JSON->new->utf8(0)->encode( $body );
            $r->content( encode_utf8( $tmpvar ) );
        }
    }

share/js/core/html.js  view on Meta::CPAN

        }, // dtable

        loginDialog: function () {
            var r = '';
            r += '<form id="loginform">';
            r += '<br><br><br>';
            r += cf('loginDialogChallengeText');
            r += '<br><br>';
            r += 'Username: <input name="nam" size="' + cf('loginDialogMaxLengthUsername') + '"';
            r += 'maxlength="' + cf('loginDialogMaxLengthUsername') + '" /><br>';
            r += 'Password: <input name="pwd" type="password" size="' + cf('loginDialogMaxLengthPassword') + '"';
            r += 'maxlength="' + cf('loginDialogMaxLengthPassword') + '" /><br><br>';
            r += '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
            r += '<input type="submit" value="Submit"><br><br>';
            r += '</form>';
            return r;
        }, // loginDialog

        logout: function () {
            var r = '';
            r += '<br><br><br>';

share/js/core/jquery-3.2.1.js  view on Meta::CPAN

/*! jQuery v3.2.1 | (c) JS Foundation and other contributors | jquery.org/license */
!function(a,b){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof windo...
a.removeEventListener("load",S),r.ready()}"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll?a.setTimeout(r.ready):(d.addEventListener("DOMContentLoaded",S),a.addEventListener("load",S));var T=function(a,b,c,d,e,f,g){var...
null==d?void 0:d))},attrHooks:{type:{set:function(a,b){if(!o.radioValue&&"radio"===b&&B(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}},removeAttr:function(a,b){var c,d=0,e=b&&b.match(L);if(e&&1===a.nodeType)while(c=e[d...

share/js/core/jquery.js  view on Meta::CPAN

/*! jQuery v3.2.1 | (c) JS Foundation and other contributors | jquery.org/license */
!function(a,b){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof windo...
a.removeEventListener("load",S),r.ready()}"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll?a.setTimeout(r.ready):(d.addEventListener("DOMContentLoaded",S),a.addEventListener("load",S));var T=function(a,b,c,d,e,f,g){var...
null==d?void 0:d))},attrHooks:{type:{set:function(a,b){if(!o.radioValue&&"radio"===b&&B(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}},removeAttr:function(a,b){var c,d=0,e=b&&b.match(L);if(e&&1===a.nodeType)while(c=e[d...



( run in 0.262 second using v1.01-cache-2.11-cpan-e9199f4ba4c )