App-Dochazka-WWW

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

- script: dochazka-www: fix option pass-through to mfile-www
- ext: add MFILE_WWW_DISPLAY_SESSION_DATA to config example
- js: int-lib: fix undefined variable in log messages
- js: dform-init: improve data entry hint
- Dispatch: fix login bypass
- Some progress on create interval "last plus offset" and non-interactive async
  dform population features
- js: display supervisor nick in employee profile

0.155 2017-10-20 22:43 CEST
- Dispatch: rename _login_dialog method to validate_user_credentials
- js: daction-init: fix pushable flag in one of the actions
- js: act-lib: use populate pattern for populateActivitiesCache
- js: implement employee profile caching
- js: upon successful masquerade, load full employee profile into cache
- js: move all cache-related code into a new caches.js module
- js: implement populateSchedIntvlsForDate() and populateSIDByDate()

0.156 2017-10-21 12:03 CEST
- build/ops: require App::MFILE::WWW 0.164
- js: fix ACL on schedule lookup/display

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

    if ( ! $method or ! $path or ! $body ) {
        $log->crit( 'POST request received, but missing mandatory attribute(s) - ' .
                    'here is the entire request body: ' . Dumper( $ajax ) );
        return 0;
    }

    # two possibilities: login/logout attempt or normal AJAX call
    if ( $method =~ m/^LOGIN/i ) {
        $log->debug( "Incoming login/logout attempt" );
        if ( $path =~ m/^login/i ) {
            return $self->validate_user_credentials( $body );
        } else {
            return $self->_logout( $body );
        }
    }

    # - normal AJAX call
    $log->debug( "Calling rest_req $method $path on session ID " . $self->session_id );
    $session->{'last_seen'} = time;
    my $rr = $self->rest_req( {
        server => $site->DOCHAZKA_WWW_BACKEND_URI,
        method => $method,
        path => $path,
        req_body => $body,
    } );
    $log->debug( "rest_req returned: " . Dumper( $rr ) );
    my $hr = $rr->{'hr'};
    return $self->_prep_ajax_response( $hr, $rr->{'body'} );
}


=head2 validate_user_credentials

Called either from C<process_post> on login AJAX requests originating from the
JavaScript side (i.e. the login screen in login-dialog.js, via login.js), or
directly from C<is_authorized> if the MFILE_WWW_BYPASS_LOGIN_DIALOG mechanism
is activated.

Returns a status object - OK means the login was successful; all other statuses
mean unsuccessful.

=cut

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

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

    $log->debug( "Employee $nick login attempt" );
    $log->debug( "DOCHAZKA_WWW_BACKEND_URI is " .  $site->DOCHAZKA_WWW_BACKEND_URI );

share/js/dochazka-www/dform-init.js  view on Meta::CPAN

            'miniMenu': {
                entries: ['createSingleIntSave'],
            }
        }); // createLastPlusOffset

        target.push('createMultipleInt', {
            'name': 'createMultipleInt',
            'type': 'dform',
            'menuText': 'Create multiple',
            'title': 'Create multiple intervals according to schedule',
            'preamble': "Hints: (1) TAB or ENTER to validate and advance to next field " +
                        "(2) enter month by name (e.g. \"June\") or number (e.g. \"6\"); " +
                        "DEFAULT: current month " +
                        "(3) enter days as " +
                        "an inclusive range (e.g. \"15-18\"), as a comma-separated list (e.g. " +
                        "\"7, 9, 28\"), or as a combination of the two (e.g. \"1, 3-5, 16-20\"); " +
                        "DEFAULT: entire month " +
                        "(4) Use 'Select activity' if you don't know activity code " +
                        '(5) Description is optional',
            'aclProfile': 'active',
            'entriesRead': [

share/js/dochazka-www/dform-init.js  view on Meta::CPAN

            'miniMenu': {
                entries: ['selectActivityAction', 'createSingleIntSave'],
            }
        }); // createNextScheduled

        target.push('createSingleInt', {
            'name': 'createSingleInt',
            'type': 'dform',
            'menuText': 'Create',
            'title': 'Create an arbitrary interval',
            'preamble': "Hints: (1) TAB or ENTER to validate and advance to next field " +
                        "(2) date YYYY-MM-DD; year is optional " +
                        "(3) time range HH:MM-HH:MM or HH:MM+HH:MM (start time plus offset) " +
                        "or +HH:MM (last existing interval plus offset) or + (next scheduled " +
                        "interval) (4) Use 'Select activity' if you don't know activity code " +
                        '(5) Description is optional',
            'aclProfile': 'active',
            'entriesWrite': [entries.iNdate, entries.iNtimerange, entries.iNact, entries.iNdesc,],
            'rememberState': true,
            'miniMenu': {
                entries: ['selectActivityAction', 'createSingleIntSave']
            }
        }); // createSingleInt

        target.push('createLock', {
            'name': 'createLock',
            'type': 'dform',
            'menuText': 'Create',
            'title': 'Create a Lock',
            'preamble': "Hints: (1) TAB or ENTER to validate and advance to next field ",
            'aclProfile': 'active',
            'entriesWrite': [entries.iNyear, entries.iNmonth,],
            'rememberState': true,
            'miniMenu': {
                entries: ['createLockSave']
            }
        }); // createLock

        target.push('createSingleIntFixedDay', {
            'name': 'createSingleIntFixedDay',
            'type': 'dform',
            'menuText': 'Create',
            'title': 'Create an arbitrary interval',
            'preamble': "Hints: (1) TAB or ENTER to validate and advance to next field " +
                        "(2) time range HH:MM-HH:MM " +
                        "(3) Use 'Select activity' if you don't know activity code " +
                        '(4) Description is optional',
            'aclProfile': 'active',
            'entriesRead': [entries.iNdate,],
            'entriesWrite': [entries.iNtimerangeNoOffset, entries.iNact, entries.iNdesc,],
            'rememberState': true,
            'miniMenu': {
                entries: ['selectActivityAction', 'createSingleIntSave']
            }

share/js/dochazka-www/dform-init.js  view on Meta::CPAN

            'miniMenu': {
                entries: ['actionEmplSearch']
            }
        }); // searchEmployee

        target.push('updateSingleInt', {
            'name': 'updateSingleInt',
            'type': 'dform',
            'menuText': 'Update',
            'title': 'Update an interval',
            'preamble': "Hints: (1) TAB or ENTER to validate and advance to next field " +
                        "(2) time range HH:MM-HH:MM " +
                        "(3) Use 'Select activity' if you don't know activity code " +
                        '(4) Description is optional',
            'aclProfile': 'active',
            'entriesRead': [entries.iNdate, entries.acTaid],
            'entriesWrite': [entries.iNtimerangeNoOffset, entries.iNact, entries.iNdesc,],
            'rememberState': true,
            'miniMenu': {
                entries: ['selectActivityAction', 'updateSingleIntSave']
            }
        }); // updateSingleInt

        target.push('viewIntervalsPrep', {
            'name': 'viewIntervalsPrep',
            'type': 'dform',
            'menuText': 'View',
            'title': 'View intervals for date or range of dates',
            'preamble': "Hints: (1) TAB or ENTER to validate and advance to next field " +
                        "(2) enter month by name (e.g. \"June\") or number (e.g. \"6\"); " +
                        "DEFAULT: current month " +
                        "(3) enter days as a singleton (e.g. \"13\") or inclusive range (e.g. \"15-18\") " +
                        "DEFAULT: entire month",
            'aclProfile': 'inactive',
            'entriesRead': [
                entries.iNdaterangeBegin,
                entries.iNdaterangeEnd,
                entries.iNyearHidden,
            ],

share/js/dochazka-www/dform-init.js  view on Meta::CPAN

            'miniMenu': {
                entries: ['viewIntervalsAction']
            }
        }); // viewIntervalsPrep

        target.push('viewLocksPrep', {
            'name': 'viewLocksPrep',
            'type': 'dform',
            'menuText': 'View',
            'title': 'View locks',
            'preamble': "Hints: (1) TAB or ENTER to validate and advance to next field " +
                        "(2) enter month by name (e.g. \"June\") or number (e.g. \"6\"); " +
                        "DEFAULT: current month ",
            'aclProfile': 'inactive',
            'entriesWrite': [
                entries.iNyear,
            ],
            'rememberState': true,
            'miniMenu': {
                entries: ['viewLocksAction']
            }

share/js/dochazka-www/int-lib.js  view on Meta::CPAN

            return true;
        },

        createMultipleIntSave = function (obj) {
            var cu = currentUser('obj'),
                daylist = $('input[id="iNdaylist"]').val(),
                month = $('input[id="iNmonth"]').val(),
                year = $('input[id="iNyear"]').val(),
                dl = daylist.split(','),
                i, rest, sc, fc;
            // validate activity
            if (obj.code) {
                console.log("Looking up activity " + obj.code + " in cache");
                i = appCaches.getActivityByCode(obj.code);
                if (! i) {
                    coreLib.displayError('Activity ' + obj.code + ' not found');
                    return null;
                }
                obj.aid = i.aid;
            } else {
                coreLib.displayError("Interval activity code missing");
                return null;
            }
            // validate day list
            if (! coreLib.isArray(dl) || dl.length === 0) {
                coreLib.displayError("Invalid day list");
                return null;
            }
            for (i = 0; i < dl.length; i += 1) {
                dl[i] = year + '-' + dt.monthToInt(month) + '-' + dl[i];
            }
            console.log("Date list", dl);
            rest = {
                "method": "POST",



( run in 0.601 second using v1.01-cache-2.11-cpan-a5abf4f5562 )