CallBackery

 view release on metacpan or  search on metacpan

CHANGES  view on Meta::CPAN

0.17.0 2019-05-31 16:02:43 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - add the triggerFormReset key to form elements, when a widget has this key
   set the form configuration will be re-queried from the server, and the 
   current content of the form will be available in $self->args. In this
   way it is possible to change settings of the form widgets based on the current
   form content, as well as altering the content of selectboxes.

0.16.0 2019-04-23 17:04:50 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - if the getUserConfig returns a sessionCookie property, start using it
   to authenticate and thus skipping the login step. this can be used to
   implement single sign on ... see bdass.

0.15.1 2019-04-03 15:44:12 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - added missing NumberFormatter to archive

0.15.0 2019-04-03 15:13:53 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - added support for numberformating ... 1000 Byte => 1 kByte 

lib/CallBackery/Controller/RpcService.pm  view on Meta::CPAN

my %allow = (
    getBaseConfig => 1,
    login => 1,
    logout => 1,
    ping => 1,
    getUserConfig => 2,
    getPluginConfig => 3,
    validatePluginData => 3,
    processPluginData => 3,
    getPluginData => 3,
    getSessionCookie => 2
);

has config => sub ($self) {
    $self->app->config;
}, weak => 1;

has user => sub ($self) {
    my $obj = $self->app->userObject->new(app=>$self->app,controller=>$self,log=>$self->log);
    return $obj;
};

lib/CallBackery/Controller/RpcService.pm  view on Meta::CPAN

=head2 ping()

check if the server is happy with our authentication state

=cut

sub ping {
    return 'pong';
}

=head2 getSessionCookie()

Return a timeestamped session cookie. For use in the X-Session-Cookie header or as a xsc field
in form submissions. Note that session cookies for form submissions are only valid for 2 seconds.
So you have to get a fresh one from the server before submitting your form.

=cut

sub getSessionCookie {
    shift->user->makeSessionCookie();
}

=head2 getConfig()

get some gloabal configuration information into the interface

=cut

sub getBaseConfig {
    my $self = shift;

lib/CallBackery/Controller/RpcService.pm  view on Meta::CPAN

=cut

async sub login { ## no critic (RequireArgUnpacking)
    my $self = shift;
    my $login = shift;
    my $password = shift;
    my $cfg = $self->config->cfgHash->{BACKEND};
    if (my $ok =
        await $self->config->promisify($self->user->login($login,$password))){
        return {
            sessionCookie => $self->user->makeSessionCookie()
        }
    } else {
        return;
    }
}

=head2 logout

Kill the session.

lib/CallBackery/User.pm  view on Meta::CPAN


=cut

has loginName => sub {
    shift->userInfo->{cbuser_login} // '*UNKNOWN*';
};


=head2 $self->sessionConf

Extracts the session config from the cookie from the X-Session-Cookie header or the xsc parameter.
If the xsc parameter is set, its timestamp must be no older than 2 seconds.

=cut

has headerSessionCookie => sub {
    my $self = shift;
    my $c = $self->controller;
    return $c->req->headers->header('X-Session-Cookie');
};

has paramSessionCookie => sub {
    my $self = shift;
    my $c = $self->controller;
    return $c->param('xsc');
};

has firstSecret => sub {
    shift->app->secrets()->[0];
};

sub isUserAuthenticated {
    my $self = shift;
    $self->userInfo->{cbuser_id} ? 1 : 0;
};

has cookieConf => sub {
    my $self = shift;
    my $headerCookie = $self->headerSessionCookie;
    my $paramCookie = $self->paramSessionCookie;

    my ($data,$check) = split /:/,($headerCookie || $paramCookie || ''),2;

    return {} if not ($data and $check);

    my $secret = $self->firstSecret;

    my $checkTest = Mojo::Util::hmac_sha1_sum($data, $secret);
    if (not secure_compare($check,$checkTest)){
        $self->log->debug(qq{Bad signed cookie possible hacking attempt.});
        return {};
    }

lib/CallBackery/User.pm  view on Meta::CPAN

    my $conf = eval {
        local $SIG{__DIE__};
        decode_json(b64_decode($data))
    };
    if ($@){
        $self->log->debug("Invalid cookie structure in '$data': $@");
        return {};
    }

    if (ref $conf ne 'HASH'){
        $self->log->debug("Cookie structure not a hash");
        return {};
    }

    if (not $conf->{t}){
        $self->log->debug("Cookie timestamp is invalid");
        return {};
    }

    if ($paramCookie and gettimeofday() - $conf->{t} > 300.0){
        $self->log->debug(qq{Cookie is expired});
        die mkerror(38445,"cookie has expired");
    }

    return $conf;
};

=head2 $user->login($login,$password)

login the user object. If login return 1 you can then makeSessionCookie.

=cut

sub login {
    my $self = shift;
    my $login = shift;
    my $password = shift;
    my $cfg = $self->app->config->cfgHash;
    my $remoteAddress = eval { $self->controller->tx->remote_address } // 'UNKNOWN_IP';
    if ($cfg->{sesame_pass} and $cfg->{sesame_user}

lib/CallBackery/User.pm  view on Meta::CPAN

    # root has all the rights
    if (($self->userId // '') eq '__ROOT'){
        return 1;
    }
    my $db = $self->db;
    my $rightId = $db->lookUp('cbright','key',$right);
    my $userId = $self->userId;
    return ($db->matchData('cbuserright',{cbuser=>$userId,cbright=>$rightId}) ? 1 : 0);
}

=head2 makeSessionCookie()

Returns a timestamped, signed session cookie containing the current userId.

=cut

sub makeSessionCookie {
    my $self = shift;
    my $timeout = shift;
    my $now = gettimeofday;
    my $conf = b64_encode(encode_json({
        u => $self->userId,
        t => $now,
    }));
    $conf =~ s/\s+//g;
    my $secret = $self->firstSecret;
    my $check = Mojo::Util::hmac_sha1_sum($conf, $secret);

lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/data/Config.js  view on Meta::CPAN

            if (base){
                base[1].split(/;/).forEach(function(kv){
                    var list = kv.split('=');
                    ha[list[0]] = decodeURIComponent(list[1]);
                });
            }
            window.location.hash = '';
            return ha;
        },

        /* if there is a sessonCookie in the userConfig start using it. This allows for seemless login */
        _applyUserConfig: function(newData,oldData) {
            if (newData.userInfo && newData.userInfo.sessionCookie) {
                callbackery.data.Server.getInstance().setSessionCookie(newData.userInfo.sessionCookie);
            }
        }

    }
});

lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/data/Server.js  view on Meta::CPAN

        this.base( arguments );
        this.set( {
            timeout: 180000,
            url: 'QX-JSON-RPC/',
            serviceName: 'default',
            protocol: 'qx1'
        });
    },

    properties: {
        sessionCookie: {
            init: null,
            nullable: true
        }
    },
    members: {
        /**
         * A asyncCall handler which tries to
         * login in the case of a permission exception.
         *
         * @param handler {Function} the callback function.

lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/data/Server.js  view on Meta::CPAN

            var origThis = this;
            var localeMgr = qx.locale.Manager.getInstance();
            var newArgs = Array.prototype.slice.call(arguments);
            newArgs[0] = function(ret, exc, id) {
                if (exc) {
                    switch (exc.code) {
                        case 6:
                            let login = callbackery.ui.Login.getInstance();
                            login.addListenerOnce('login', (e) => {
                                let ret = e.getData();
                                origThis.setSessionCookie(ret.sessionCookie);
                                origArguments.callee.base.apply(origThis, origArguments);
                            });
                            login.open();
                            return;
                        case 7:
                            if (window.console){
                                window.console.log("Session Expired. Reloading page");
                            }
                            callbackery.ui.Busy.getInstance().vanish();
                            let mb = callbackery.ui.MsgBox.getInstance()

lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/data/Server.js  view on Meta::CPAN

            var newArgs = Array.prototype.slice.call(arguments);
            newArgs[0] = superHandler;
            busy.manifest('Runnning ' + methodName);
            this.callAsync.apply(this, newArgs);
        },
        /**
         * override the request creation, to add our 'cookie' header
         */
        createRequest: function() {
            var req = this.base(arguments);
            var cookie = this.getSessionCookie();
            if (cookie) {
                req.setRequestHeader('X-Session-Cookie', this.getSessionCookie());
            }
            return req;
        }
    }
});

lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/ui/Login.js  view on Meta::CPAN

            iframe.setAttribute('src',
                'login?nocache='+Math.round(1000000*Math.random()).toString(16));
            return iframe;
        },
        __getIframeDocument: function(){
            var iframe = this.__iframe;
            return iframe.contentWindow ? iframe.contentWindow.document : iframe.contentDocument;
        },
        __loginHandler : function(ret, exc) {
            if (exc == null) {
                if (qx.lang.Type.isObject(ret) && ret.sessionCookie) {
                    // submit the iframe form to trigger the browser to save the password
                    this.__getIframeDocument().getElementById('cbLoginForm').submit();
                    this.fireDataEvent('login', ret);
                    this.close();
                }
                else {
                    var element = this.getContentElement().getDomElement();
                    var tada = {duration: 1000, keyFrames : {
                        0 :  {scale: 1, rotate: "0deg"},
                        10 : {scale: 0.9, rotate: "-3deg"},

lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/ui/plugin/Action.js  view on Meta::CPAN

                                            that.xtr(response.exception.message) + " (" + response.exception.code + ")"
                                        );
                                    }
                                    that.getApplicationRoot().remove(iframe);
                                    if (btCfg.closeAfterDownload) {
                                        that.fireDataEvent('actionResponse', { action: 'cancel' });
                                    }
                                });
                                iframe.setSource(url);
                                that.getApplicationRoot().add(iframe, { top: -1000, left: -1000 });
                            }, 'getSessionCookie');
                            break;
                        case 'cancel':
                            this.fireDataEvent('actionResponse', { action: 'cancel' });
                            break;
                        case 'wizzard':
                            var parent = that.getLayoutParent();
                            while (!parent.classname.match(/Page|Popup/)) {
                                parent = parent.getLayoutParent();
                            }
                            // This could in principal work for Page although.

lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/ui/plugin/Action.js  view on Meta::CPAN

                if (formData && fileList) {
                    var form = new FormData();
                    form.append('name', name);
                    form.append('key', key);
                    form.append('file', fileList[0]);
                    form.append('formData', qx.lang.Json.stringify(formData));
                    var that = this;
                    serverCall.callAsyncSmart(function (cookie) {
                        form.append('xsc', cookie);
                        that._uploadForm(form,btCfg.busyMessage);
                    }, 'getSessionCookie');
                } else {
                    callbackery.ui.MsgBox.getInstance().error(
                        this.tr("Upload Exception"),
                        this.tr("Make sure to select a file and properly fill the form")
                    );
                }
            }, this);

            return button;
        },



( run in 2.180 seconds using v1.01-cache-2.11-cpan-e9199f4ba4c )