Mojolicious-Plugin-WebPush

 view release on metacpan or  search on metacpan

README.md  view on Meta::CPAN

# SYNOPSIS

    # Mojolicious::Lite
    my $sw = plugin 'ServiceWorker' => { debug => 1 };
    my $webpush = plugin 'WebPush' => {
      save_endpoint => '/api/savesubs',
      subs_session2user_p => \&subs_session2user_p,
      subs_create_p => \&subs_create_p,
      subs_read_p => \&subs_read_p,
      subs_delete_p => \&subs_delete_p,
      ecc_private_key => 'vapid_private_key.pem',
      claim_sub => "mailto:admin@example.com",
    };

    sub subs_session2user_p {
      my ($c, $session) = @_;
      return Mojo::Promise->reject("Session not logged in") if !$session->{user_id};
      Mojo::Promise->resolve($session->{user_id});
    }

    sub subs_create_p {

README.md  view on Meta::CPAN

## webpush.delete\_p

    $c->webpush->delete_p($user_id)->then(sub {
      $c->render(json => { data => { success => \1 } });
    });

## webpush.authorization

    my $header_value = $c->webpush->authorization($subs_info);

Won't function without ["claim\_sub"](#claim_sub) and ["ecc\_private\_key"](#ecc_private_key), or
`$subs_info` having a valid URL to get the base of as the `aud`
claim. Returns a suitable `Authorization` header value to send to
a push service.  Valid for a period defined by ["claim\_exp\_offset"](#claim_exp_offset).
but could become so to avoid unnecessary computation.

## webpush.public\_key

    my $pkey = $c->webpush->public_key;

Gives the app's public VAPID key, calculated from the private key.

examples/app.pl  view on Meta::CPAN

use Mojolicious::Lite;
use Mojo::File qw(curfile path);
use Mojo::Promise;
use Mojo::SQLite;
use Mojo::JSON qw(decode_json encode_json);

my $pushkeyfile = curfile->sibling('webpush_private_key.pem')
  ->to_rel(path)->to_string;
if (! -f $pushkeyfile) {
  die <<EOF;
No webpush private key file found in '$pushkeyfile'. Make one:
  $0 webpush keygen >$pushkeyfile
EOF
}

helper sqlite => sub {
  state $path = app->home->child( 'data.db' );

examples/app.pl  view on Meta::CPAN

  $_[0]->render(json => { user_id => $_[0]->session('user_id') });
}, 'whoami';

sub webpush_config {
  +{
    save_endpoint => '/api/savesubs',
    subs_session2user_p => \&subs_session2user_p,
    subs_create_p => \&subs_create_p,
    subs_read_p => \&subs_read_p,
    subs_delete_p => \&subs_delete_p,
    (-s $pushkeyfile ? (ecc_private_key => $pushkeyfile) : ()),
    claim_sub => 'mailto:admin@example.com',
  };
}

sub subs_session2user_p {
  return Mojo::Promise->reject("Session not logged in") if !$_[1]{user_id};
  Mojo::Promise->resolve($_[1]{user_id});
}

sub subs_create_p {

lib/Mojolicious/Command/webpush.pm  view on Meta::CPAN


Mojolicious::Command::webpush - Manage your app's web-push

=head1 SYNOPSIS

  Usage: APPLICATION webpush COMMAND [OPTIONS]

    ./myapp.pl webpush create <USERID> <JSON>
    ./myapp.pl webpush read <USERID>
    ./myapp.pl webpush delete <USERID>
    ./myapp.pl webpush keygen > webpush_private_key.pem

  Options:
    -h, --help          Show this summary of available options
        --home <path>   Path to home directory of your application, defaults to
                        the value of MOJO_HOME or auto-detection
    -m, --mode <name>   Operating mode for your application, defaults to the
                        value of MOJO_MODE/PLACK_ENV or "development"

=head1 DESCRIPTION

lib/Mojolicious/Plugin/WebPush.pm  view on Meta::CPAN


our $VERSION = '0.05';

my @MANDATORY_CONF = qw(
  subs_session2user_p
  save_endpoint
  subs_create_p
  subs_read_p
  subs_delete_p
);
my @AUTH_CONF = qw(claim_sub ecc_private_key);
my $DEFAULT_PUSH_HANDLER = <<'EOF';
event => {
  var msg = event.data.json();
  var title = msg.title;
  delete msg.title;
  event.waitUntil(self.registration.showNotification(title, msg));
}
EOF

sub _decode {

lib/Mojolicious/Plugin/WebPush.pm  view on Meta::CPAN

    )->then(
      sub { $c->render(json => { data => { success => \1 } }) },
      sub { _error($c, @_) },
    );
  };
}

sub _make_auth_helper {
  my ($app, $conf) = @_;
  my $exp_offset = $conf->{claim_exp_offset} || 86400;
  my $key = Crypt::PK::ECC->new($conf->{ecc_private_key});
  my $claims_start = { sub => $conf->{claim_sub} };
  my $pkey = encode_base64url $key->export_key_raw('public');
  $app->helper('webpush.public_key' => sub { $pkey });
  sub {
    my ($c, $subs_info) = @_;
    my $aud = Mojo::URL->new($subs_info->{endpoint})->path(Mojo::Path->new->trailing_slash(0)).'';
    my $claims = { aud => $aud, exp => time + $exp_offset, %$claims_start };
    my $token = encode_jwt key => $key, alg => 'ES256', payload => $claims;
    "vapid t=$token,k=$pkey";
  };

lib/Mojolicious/Plugin/WebPush.pm  view on Meta::CPAN

=head1 SYNOPSIS

  # Mojolicious::Lite
  my $sw = plugin 'ServiceWorker' => { debug => 1 };
  my $webpush = plugin 'WebPush' => {
    save_endpoint => '/api/savesubs',
    subs_session2user_p => \&subs_session2user_p,
    subs_create_p => \&subs_create_p,
    subs_read_p => \&subs_read_p,
    subs_delete_p => \&subs_delete_p,
    ecc_private_key => 'vapid_private_key.pem',
    claim_sub => "mailto:admin@example.com",
  };

  sub subs_session2user_p {
    my ($c, $session) = @_;
    return Mojo::Promise->reject("Session not logged in") if !$session->{user_id};
    Mojo::Promise->resolve($session->{user_id});
  }

  sub subs_create_p {

lib/Mojolicious/Plugin/WebPush.pm  view on Meta::CPAN

=over

=item *

The opaque information your app uses to identify the user.

=back

Returns a promise of the deletion result. Must reject if not found.

=head2 ecc_private_key

A value to be passed to L<Crypt::PK::ECC/new>: a simple scalar is a
filename, a scalar-ref is the actual key. If not provided,
L</webpush.authorization> will (obviously) not be able to function.

=head2 claim_sub

A value to be used as the C<sub> claim by the L</webpush.authorization>,
which needs it. Must be either an HTTPS or C<mailto:> URL.

lib/Mojolicious/Plugin/WebPush.pm  view on Meta::CPAN

=head2 webpush.delete_p

  $c->webpush->delete_p($user_id)->then(sub {
    $c->render(json => { data => { success => \1 } });
  });

=head2 webpush.authorization

  my $header_value = $c->webpush->authorization($subs_info);

Won't function without L</claim_sub> and L</ecc_private_key>, or
C<$subs_info> having a valid URL to get the base of as the C<aud>
claim. Returns a suitable C<Authorization> header value to send to
a push service.  Valid for a period defined by L</claim_exp_offset>.
but could become so to avoid unnecessary computation.

=head2 webpush.public_key

  my $pkey = $c->webpush->public_key;

Gives the app's public VAPID key, calculated from the private key.

t/lib/TestUtils.pm  view on Meta::CPAN

  Crypt::PK::ECC->new(\$T_PRIVATE_PEM)->export_key_raw('public')
);

sub webpush_config {
  +{
    save_endpoint => $ENDPOINT,
    subs_session2user_p => \&subs_session2user_p,
    subs_create_p => \&subs_create_p,
    subs_read_p => \&subs_read_p,
    subs_delete_p => \&subs_delete_p,
    ecc_private_key => \$T_PRIVATE_PEM,
    claim_sub => $SUB,
  };
}

sub subs_session2user_p {
  my($c, $session) = @_;
  my $user_id = $session->{user_id}
    or return Mojo::Promise->reject("Session not logged in");
  Mojo::Promise->resolve($user_id);
}



( run in 0.251 second using v1.01-cache-2.11-cpan-4d50c553e7e )