diff --git a/.idea/php.xml b/.idea/php.xml index 3f70f6c..b5ac20c 100644 --- a/.idea/php.xml +++ b/.idea/php.xml @@ -123,6 +123,18 @@ + + + + + + + + + + + + diff --git a/.idea/skolehjem-webapp.iml b/.idea/skolehjem-webapp.iml index 1c12b7e..cf75c6e 100644 --- a/.idea/skolehjem-webapp.iml +++ b/.idea/skolehjem-webapp.iml @@ -21,6 +21,7 @@ + @@ -32,6 +33,7 @@ + @@ -41,6 +43,7 @@ + @@ -69,6 +72,8 @@ + + @@ -91,6 +96,7 @@ + @@ -119,10 +125,16 @@ + + + + + + diff --git a/skolehjem/app/Http/Controllers/NewsController.php b/skolehjem/app/Http/Controllers/NewsController.php index 475eb80..5234cc7 100644 --- a/skolehjem/app/Http/Controllers/NewsController.php +++ b/skolehjem/app/Http/Controllers/NewsController.php @@ -73,7 +73,7 @@ class NewsController extends Controller $news->save(); Helpers::sendNewsNotification($news, User::query()->where("wants_emails", "=", true)->get()); - + PushNotificationController::push(); return redirect()->route("news.index"); } @@ -91,7 +91,7 @@ class NewsController extends Controller $news->save(); Helpers::sendNewsNotification($news, User::query()->where("wants_emails", "=", true)->get()); - + PushNotificationController::push(); return $news; } diff --git a/skolehjem/app/Http/Controllers/PushNotificationController.php b/skolehjem/app/Http/Controllers/PushNotificationController.php new file mode 100644 index 0000000..05e625b --- /dev/null +++ b/skolehjem/app/Http/Controllers/PushNotificationController.php @@ -0,0 +1,50 @@ +middleware('auth'); + } + + /** + * Store the PushSubscription. + * + * @param Request $request + * @return JsonResponse + * @throws ValidationException + */ + public function store(Request $request){ + $this->validate($request,[ + 'endpoint' => 'required', + 'keys.auth' => 'required', + 'keys.p256dh' => 'required' + ]); + $endpoint = $request->endpoint; + $token = $request->keys['auth']; + $key = $request->keys['p256dh']; + $user = Auth::user(); + $user->updatePushSubscription($endpoint, $key, $token); + + return response()->json(['success' => true],200); + } + + /** + * Send Push Notifications to all users. + * + * @return RedirectResponse + */ + static public function push(){ + \Illuminate\Support\Facades\Notification::send(User::all(), new PushNews); + } +} diff --git a/skolehjem/app/Notifications/PushNews.php b/skolehjem/app/Notifications/PushNews.php new file mode 100644 index 0000000..745e75d --- /dev/null +++ b/skolehjem/app/Notifications/PushNews.php @@ -0,0 +1,66 @@ +title('Ny Nyhed') + ->icon('/images/icons/appIcon.png') + ->body('Der er en ny nyhed i ekapp\'en') + ->action('Se nyheder', 'root.index'); + } + + /** + * Get the mail representation of the notification. + * + * @param mixed $notifiable + * @return \Illuminate\Notifications\Messages\MailMessage + */ + public function toMail($notifiable) + { + return (new MailMessage) + ->line('The introduction to the notification.') + ->action('Notification Action', url('/')) + ->line('Thank you for using our application!'); + } + + /** + * Get the array representation of the notification. + * + * @param mixed $notifiable + * @return array + */ + public function toArray($notifiable) + { + return [ + // + ]; + } +} diff --git a/skolehjem/app/Providers/AppServiceProvider.php b/skolehjem/app/Providers/AppServiceProvider.php index d97721b..46af969 100644 --- a/skolehjem/app/Providers/AppServiceProvider.php +++ b/skolehjem/app/Providers/AppServiceProvider.php @@ -2,6 +2,7 @@ namespace App\Providers; +use Illuminate\Support\Facades\Schema; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider @@ -23,6 +24,7 @@ class AppServiceProvider extends ServiceProvider */ public function boot() { + Schema::defaultStringLength(191); if(env('HTTPS_ONLY') == true) url()->forceScheme('https'); } diff --git a/skolehjem/app/User.php b/skolehjem/app/User.php index 220a042..33d101a 100644 --- a/skolehjem/app/User.php +++ b/skolehjem/app/User.php @@ -15,12 +15,14 @@ use Illuminate\Notifications\Notifiable; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Hash; use Spatie\Permission\Traits\HasRoles; +use NotificationChannels\WebPush\HasPushSubscriptions; //Class of which should extend Model Library class User extends Authenticatable { use Notifiable; use HasRoles; + use HasPushSubscriptions; /** * The attributes that are mass assignable. diff --git a/skolehjem/composer.json b/skolehjem/composer.json index 8cd540d..e6c1656 100644 --- a/skolehjem/composer.json +++ b/skolehjem/composer.json @@ -14,6 +14,7 @@ "fruitcake/laravel-cors": "^1.0", "guzzlehttp/guzzle": "^6.3", "jenssegers/agent": "^2.6", + "laravel-notification-channels/webpush": "^5.0", "laravel/framework": "^7.0", "laravel/tinker": "^2.0", "laravel/ui": "^2.0", diff --git a/skolehjem/composer.lock b/skolehjem/composer.lock index 7c857bf..7664763 100644 --- a/skolehjem/composer.lock +++ b/skolehjem/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "8e62a745d683f5494f4d1efefc047dfd", + "content-hash": "9562cdf6050fb06efafd3cb75e033080", "packages": [ { "name": "asm89/stack-cors", @@ -510,6 +510,77 @@ ], "time": "2020-02-13T22:36:52+00:00" }, + { + "name": "fgrosse/phpasn1", + "version": "v2.2.0", + "source": { + "type": "git", + "url": "https://github.com/fgrosse/PHPASN1.git", + "reference": "d1978f7abd580f3fc33561e7f71d4c12c7531fad" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/fgrosse/PHPASN1/zipball/d1978f7abd580f3fc33561e7f71d4c12c7531fad", + "reference": "d1978f7abd580f3fc33561e7f71d4c12c7531fad", + "shasum": "" + }, + "require": { + "php": ">=7.0.0" + }, + "require-dev": { + "phpunit/phpunit": "~6.3", + "satooshi/php-coveralls": "~2.0" + }, + "suggest": { + "ext-bcmath": "BCmath is the fallback extension for big integer calculations", + "ext-curl": "For loading OID information from the web if they have not bee defined statically", + "ext-gmp": "GMP is the preferred extension for big integer calculations", + "phpseclib/bcmath_compat": "BCmath polyfill for servers where neither GMP nor BCmath is available" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "FG\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Friedrich Große", + "email": "friedrich.grosse@gmail.com", + "homepage": "https://github.com/FGrosse", + "role": "Author" + }, + { + "name": "All contributors", + "homepage": "https://github.com/FGrosse/PHPASN1/contributors" + } + ], + "description": "A PHP Framework that allows you to encode and decode arbitrary ASN.1 structures using the ITU-T X.690 Encoding Rules.", + "homepage": "https://github.com/FGrosse/PHPASN1", + "keywords": [ + "DER", + "asn.1", + "asn1", + "ber", + "binary", + "decoding", + "encoding", + "x.509", + "x.690", + "x509", + "x690" + ], + "time": "2020-10-11T16:28:18+00:00" + }, { "name": "fideloper/proxy", "version": "4.3.0", @@ -939,6 +1010,60 @@ ], "time": "2020-06-13T08:05:20+00:00" }, + { + "name": "laravel-notification-channels/webpush", + "version": "5.0.3", + "source": { + "type": "git", + "url": "https://github.com/laravel-notification-channels/webpush.git", + "reference": "0623c5abee570fed18ceded75f1d1ec6b2831996" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel-notification-channels/webpush/zipball/0623c5abee570fed18ceded75f1d1ec6b2831996", + "reference": "0623c5abee570fed18ceded75f1d1ec6b2831996", + "shasum": "" + }, + "require": { + "illuminate/notifications": "^5.3|^6.0|^7.0|^8.0", + "illuminate/support": "^5.1|^6.0|^7.0|^8.0", + "minishlink/web-push": "^6.0", + "php": "^7.2" + }, + "require-dev": { + "mockery/mockery": "~1.0", + "orchestra/testbench": "^4.0", + "phpunit/phpunit": "^8.5" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "NotificationChannels\\WebPush\\WebPushServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "NotificationChannels\\WebPush\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Cretu Eusebiu", + "email": "me@cretueusebiu.com", + "homepage": "http://cretueusebiu.com", + "role": "Developer" + } + ], + "description": "Web Push Notifications driver for Laravel.", + "homepage": "https://github.com/laravel-notification-channels/webpush", + "time": "2020-09-19T02:27:08+00:00" + }, { "name": "laravel/framework", "version": "v7.14.1", @@ -1440,6 +1565,65 @@ ], "time": "2020-05-18T15:13:39+00:00" }, + { + "name": "minishlink/web-push", + "version": "v6.0.3", + "source": { + "type": "git", + "url": "https://github.com/web-push-libs/web-push-php.git", + "reference": "8911bad58026db19ab5e39d19341ea9925cb1edb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/web-push-libs/web-push-php/zipball/8911bad58026db19ab5e39d19341ea9925cb1edb", + "reference": "8911bad58026db19ab5e39d19341ea9925cb1edb", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "ext-json": "*", + "ext-mbstring": "*", + "ext-openssl": "*", + "guzzlehttp/guzzle": "^7.0.1|^6.2", + "php": ">=7.2", + "web-token/jwt-key-mgmt": "^2.0", + "web-token/jwt-signature": "^2.0", + "web-token/jwt-signature-algorithm-ecdsa": "^2.0", + "web-token/jwt-util-ecc": "^2.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.14", + "phpstan/phpstan": "^0.11|^0.12", + "phpunit/phpunit": "^8.0|^9.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Minishlink\\WebPush\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Louis Lagrange", + "email": "lagrange.louis@gmail.com", + "homepage": "https://github.com/Minishlink" + } + ], + "description": "Web Push library for PHP", + "homepage": "https://github.com/web-push-libs/web-push-php", + "keywords": [ + "Push API", + "WebPush", + "notifications", + "push", + "web" + ], + "time": "2020-11-06T10:06:32+00:00" + }, { "name": "mobiledetect/mobiledetectlib", "version": "2.8.34", @@ -2002,6 +2186,107 @@ ], "time": "2019-01-08T18:20:26+00:00" }, + { + "name": "psr/http-client", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-client.git", + "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", + "keywords": [ + "http", + "http-client", + "psr", + "psr-18" + ], + "time": "2020-06-29T06:28:15+00:00" + }, + { + "name": "psr/http-factory", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "shasum": "" + }, + "require": { + "php": ">=7.0.0", + "psr/http-message": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "time": "2019-04-30T12:38:16+00:00" + }, { "name": "psr/http-message", "version": "1.0.1", @@ -2514,6 +2799,67 @@ ], "time": "2020-05-20T00:31:29+00:00" }, + { + "name": "spomky-labs/base64url", + "version": "v2.0.4", + "source": { + "type": "git", + "url": "https://github.com/Spomky-Labs/base64url.git", + "reference": "7752ce931ec285da4ed1f4c5aa27e45e097be61d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Spomky-Labs/base64url/zipball/7752ce931ec285da4ed1f4c5aa27e45e097be61d", + "reference": "7752ce931ec285da4ed1f4c5aa27e45e097be61d", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "require-dev": { + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^0.11|^0.12", + "phpstan/phpstan-beberlei-assert": "^0.11|^0.12", + "phpstan/phpstan-deprecation-rules": "^0.11|^0.12", + "phpstan/phpstan-phpunit": "^0.11|^0.12", + "phpstan/phpstan-strict-rules": "^0.11|^0.12" + }, + "type": "library", + "autoload": { + "psr-4": { + "Base64Url\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Florent Morselli", + "homepage": "https://github.com/Spomky-Labs/base64url/contributors" + } + ], + "description": "Base 64 URL Safe Encoding/Decoding PHP Library", + "homepage": "https://github.com/Spomky-Labs/base64url", + "keywords": [ + "base64", + "rfc4648", + "safe", + "url" + ], + "funding": [ + { + "url": "https://github.com/Spomky", + "type": "github" + }, + { + "url": "https://www.patreon.com/FlorentMorselli", + "type": "patreon" + } + ], + "time": "2020-11-03T09:10:25+00:00" + }, { "name": "swiftmailer/swiftmailer", "version": "v6.2.3", @@ -4299,6 +4645,138 @@ ], "time": "2020-06-24T13:36:18+00:00" }, + { + "name": "thecodingmachine/safe", + "version": "v0.1.16", + "source": { + "type": "git", + "url": "https://github.com/thecodingmachine/safe.git", + "reference": "4e8f840f0a0a2ea167813c3994a7fc527c3c2182" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thecodingmachine/safe/zipball/4e8f840f0a0a2ea167813c3994a7fc527c3c2182", + "reference": "4e8f840f0a0a2ea167813c3994a7fc527c3c2182", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "require-dev": { + "phpstan/phpstan": "^0.10.3", + "squizlabs/php_codesniffer": "^3.2", + "thecodingmachine/phpstan-strict-rules": "^0.10.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.1-dev" + } + }, + "autoload": { + "psr-4": { + "Safe\\": [ + "lib/", + "generated/" + ] + }, + "files": [ + "generated/apache.php", + "generated/apc.php", + "generated/apcu.php", + "generated/array.php", + "generated/bzip2.php", + "generated/classobj.php", + "generated/com.php", + "generated/cubrid.php", + "generated/curl.php", + "generated/datetime.php", + "generated/dir.php", + "generated/eio.php", + "generated/errorfunc.php", + "generated/exec.php", + "generated/fileinfo.php", + "generated/filesystem.php", + "generated/filter.php", + "generated/fpm.php", + "generated/ftp.php", + "generated/funchand.php", + "generated/gmp.php", + "generated/gnupg.php", + "generated/hash.php", + "generated/ibase.php", + "generated/ibmDb2.php", + "generated/iconv.php", + "generated/image.php", + "generated/imap.php", + "generated/info.php", + "generated/ingres-ii.php", + "generated/inotify.php", + "generated/json.php", + "generated/ldap.php", + "generated/libevent.php", + "generated/libxml.php", + "generated/lzf.php", + "generated/mailparse.php", + "generated/mbstring.php", + "generated/misc.php", + "generated/msql.php", + "generated/mssql.php", + "generated/mysql.php", + "generated/mysqli.php", + "generated/mysqlndMs.php", + "generated/mysqlndQc.php", + "generated/network.php", + "generated/oci8.php", + "generated/opcache.php", + "generated/openssl.php", + "generated/outcontrol.php", + "generated/password.php", + "generated/pcntl.php", + "generated/pcre.php", + "generated/pdf.php", + "generated/pgsql.php", + "generated/posix.php", + "generated/ps.php", + "generated/pspell.php", + "generated/readline.php", + "generated/rrd.php", + "generated/sem.php", + "generated/session.php", + "generated/shmop.php", + "generated/simplexml.php", + "generated/sockets.php", + "generated/sodium.php", + "generated/solr.php", + "generated/spl.php", + "generated/sqlsrv.php", + "generated/ssdeep.php", + "generated/ssh2.php", + "generated/stats.php", + "generated/stream.php", + "generated/strings.php", + "generated/swoole.php", + "generated/uodbc.php", + "generated/uopz.php", + "generated/url.php", + "generated/var.php", + "generated/xdiff.php", + "generated/xml.php", + "generated/xmlrpc.php", + "generated/yaml.php", + "generated/yaz.php", + "generated/zip.php", + "generated/zlib.php", + "lib/special_cases.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHP core functions that throw exceptions instead of returning FALSE on error", + "time": "2019-06-25T08:45:33+00:00" + }, { "name": "tijsverkoyen/css-to-inline-styles", "version": "2.2.2", @@ -4459,6 +4937,417 @@ "php" ], "time": "2020-05-26T06:40:44+00:00" + }, + { + "name": "web-token/jwt-core", + "version": "v2.2.3", + "source": { + "type": "git", + "url": "https://github.com/web-token/jwt-core.git", + "reference": "0909efa4fe2c3e2d537922b3ea1b65eb8203686c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/web-token/jwt-core/zipball/0909efa4fe2c3e2d537922b3ea1b65eb8203686c", + "reference": "0909efa4fe2c3e2d537922b3ea1b65eb8203686c", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-mbstring": "*", + "fgrosse/phpasn1": "^2.0", + "php": ">=7.2", + "spomky-labs/base64url": "^1.0|^2.0" + }, + "conflict": { + "spomky-labs/jose": "*" + }, + "require-dev": { + "phpunit/phpunit": "^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "v1.0": "1.0.x-dev", + "v1.1": "1.1.x-dev", + "v1.2": "1.2.x-dev", + "v1.3": "1.3.x-dev", + "v2.0": "2.0.x-dev", + "v2.1": "2.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Jose\\Component\\Core\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Florent Morselli", + "homepage": "https://github.com/Spomky" + }, + { + "name": "All contributors", + "homepage": "https://github.com/web-token/jwt-framework/contributors" + } + ], + "description": "Core component of the JWT Framework.", + "homepage": "https://github.com/web-token", + "keywords": [ + "JOSE", + "JWE", + "JWK", + "JWKSet", + "JWS", + "Jot", + "RFC7515", + "RFC7516", + "RFC7517", + "RFC7518", + "RFC7519", + "RFC7520", + "bundle", + "jwa", + "jwt", + "symfony" + ], + "funding": [ + { + "url": "https://www.patreon.com/FlorentMorselli", + "type": "patreon" + } + ], + "time": "2020-08-22T13:17:25+00:00" + }, + { + "name": "web-token/jwt-key-mgmt", + "version": "v2.2.5", + "source": { + "type": "git", + "url": "https://github.com/web-token/jwt-key-mgmt.git", + "reference": "03fafa105970f0e5a7ae44c39bc8f0576ebcb23b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/web-token/jwt-key-mgmt/zipball/03fafa105970f0e5a7ae44c39bc8f0576ebcb23b", + "reference": "03fafa105970f0e5a7ae44c39bc8f0576ebcb23b", + "shasum": "" + }, + "require": { + "ext-openssl": "*", + "psr/http-client": "^1.0", + "psr/http-factory": "^1.0", + "web-token/jwt-core": "^2.0" + }, + "require-dev": { + "php-http/httplug": "^1.1", + "php-http/message-factory": "^1.0", + "php-http/mock-client": "^1.0", + "phpunit/phpunit": "^8.0" + }, + "suggest": { + "ext-sodium": "Sodium is required for OKP key creation, EdDSA signature algorithm and ECDH-ES key encryption with OKP keys", + "php-http/httplug": "To enable JKU/X5U support.", + "php-http/message-factory": "To enable JKU/X5U support.", + "web-token/jwt-util-ecc": "To use EC key analyzers." + }, + "type": "library", + "extra": { + "branch-alias": { + "v1.0": "1.0.x-dev", + "v1.1": "1.1.x-dev", + "v1.2": "1.2.x-dev", + "v1.3": "1.3.x-dev", + "v2.0": "2.0.x-dev", + "v2.1": "2.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Jose\\Component\\KeyManagement\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Florent Morselli", + "homepage": "https://github.com/Spomky" + }, + { + "name": "All contributors", + "homepage": "https://github.com/web-token/jwt-key-mgmt/contributors" + } + ], + "description": "Key Management component of the JWT Framework.", + "homepage": "https://github.com/web-token", + "keywords": [ + "JOSE", + "JWE", + "JWK", + "JWKSet", + "JWS", + "Jot", + "RFC7515", + "RFC7516", + "RFC7517", + "RFC7518", + "RFC7519", + "RFC7520", + "bundle", + "jwa", + "jwt", + "symfony" + ], + "funding": [ + { + "url": "https://www.patreon.com/FlorentMorselli", + "type": "patreon" + } + ], + "time": "2020-08-01T11:57:29+00:00" + }, + { + "name": "web-token/jwt-signature", + "version": "v2.2.5", + "source": { + "type": "git", + "url": "https://github.com/web-token/jwt-signature.git", + "reference": "f4d83f77031c9d27edebbea053931074030d3b09" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/web-token/jwt-signature/zipball/f4d83f77031c9d27edebbea053931074030d3b09", + "reference": "f4d83f77031c9d27edebbea053931074030d3b09", + "shasum": "" + }, + "require": { + "web-token/jwt-core": "^2.1" + }, + "require-dev": { + "phpunit/phpunit": "^8.0" + }, + "suggest": { + "web-token/jwt-signature-algorithm-ecdsa": "ECDSA Based Signature Algorithms", + "web-token/jwt-signature-algorithm-eddsa": "EdDSA Based Signature Algorithms", + "web-token/jwt-signature-algorithm-experimental": "Experimental Signature Algorithms", + "web-token/jwt-signature-algorithm-hmac": "HMAC Based Signature Algorithms", + "web-token/jwt-signature-algorithm-none": "None Signature Algorithm", + "web-token/jwt-signature-algorithm-rsa": "RSA Based Signature Algorithms" + }, + "type": "library", + "extra": { + "branch-alias": { + "v1.0": "1.0.x-dev", + "v1.1": "1.1.x-dev", + "v1.2": "1.2.x-dev", + "v1.3": "1.3.x-dev", + "v2.0": "2.0.x-dev", + "v2.1": "2.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Jose\\Component\\Signature\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Florent Morselli", + "homepage": "https://github.com/Spomky" + }, + { + "name": "All contributors", + "homepage": "https://github.com/web-token/jwt-signature/contributors" + } + ], + "description": "Signature component of the JWT Framework.", + "homepage": "https://github.com/web-token", + "keywords": [ + "JOSE", + "JWE", + "JWK", + "JWKSet", + "JWS", + "Jot", + "RFC7515", + "RFC7516", + "RFC7517", + "RFC7518", + "RFC7519", + "RFC7520", + "bundle", + "jwa", + "jwt", + "symfony" + ], + "funding": [ + { + "url": "https://www.patreon.com/FlorentMorselli", + "type": "patreon" + } + ], + "time": "2020-08-01T11:48:26+00:00" + }, + { + "name": "web-token/jwt-signature-algorithm-ecdsa", + "version": "v2.2.5", + "source": { + "type": "git", + "url": "https://github.com/web-token/jwt-signature-algorithm-ecdsa.git", + "reference": "3ae6e56ccf34e8b7b65ec988497d5d1bceca9864" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/web-token/jwt-signature-algorithm-ecdsa/zipball/3ae6e56ccf34e8b7b65ec988497d5d1bceca9864", + "reference": "3ae6e56ccf34e8b7b65ec988497d5d1bceca9864", + "shasum": "" + }, + "require": { + "ext-openssl": "*", + "web-token/jwt-signature": "^2.0" + }, + "require-dev": { + "phpunit/phpunit": "^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "v1.0": "1.0.x-dev", + "v1.1": "1.1.x-dev", + "v1.2": "1.2.x-dev", + "v1.3": "1.3.x-dev", + "v2.0": "2.0.x-dev", + "v2.1": "2.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Jose\\Component\\Signature\\Algorithm\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Florent Morselli", + "homepage": "https://github.com/Spomky" + }, + { + "name": "All contributors", + "homepage": "https://github.com/web-token/jwt-framework/contributors" + } + ], + "description": "ECDSA Based Signature Algorithms the JWT Framework.", + "homepage": "https://github.com/web-token", + "keywords": [ + "JOSE", + "JWE", + "JWK", + "JWKSet", + "JWS", + "Jot", + "RFC7515", + "RFC7516", + "RFC7517", + "RFC7518", + "RFC7519", + "RFC7520", + "bundle", + "jwa", + "jwt", + "symfony" + ], + "funding": [ + { + "url": "https://www.patreon.com/FlorentMorselli", + "type": "patreon" + } + ], + "time": "2020-08-22T13:17:25+00:00" + }, + { + "name": "web-token/jwt-util-ecc", + "version": "v2.0.8", + "source": { + "type": "git", + "url": "https://github.com/web-token/jwt-util-ecc.git", + "reference": "41d6612876b9cb001bb36883100c322130958432" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/web-token/jwt-util-ecc/zipball/41d6612876b9cb001bb36883100c322130958432", + "reference": "41d6612876b9cb001bb36883100c322130958432", + "shasum": "" + }, + "require": { + "thecodingmachine/safe": "^0.1.14" + }, + "require-dev": { + "phpunit/phpunit": "^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "v1.0": "1.0.x-dev", + "v1.1": "1.1.x-dev", + "v1.2": "1.2.x-dev", + "v1.3": "1.3.x-dev", + "v2.0": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Jose\\Component\\Core\\Util\\Ecc\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Florent Morselli", + "homepage": "https://github.com/Spomky" + }, + { + "name": "All contributors", + "homepage": "https://github.com/web-token/jwt-core/contributors" + } + ], + "description": "ECC Tools for the JWT Framework.", + "homepage": "https://github.com/web-token", + "keywords": [ + "JOSE", + "JWE", + "JWK", + "JWKSet", + "JWS", + "Jot", + "RFC7515", + "RFC7516", + "RFC7517", + "RFC7518", + "RFC7519", + "RFC7520", + "bundle", + "jwa", + "jwt", + "symfony" + ], + "time": "2019-06-22T13:06:07+00:00" } ], "packages-dev": [ diff --git a/skolehjem/config/webpush.php b/skolehjem/config/webpush.php new file mode 100644 index 0000000..cb75641 --- /dev/null +++ b/skolehjem/config/webpush.php @@ -0,0 +1,42 @@ + [ + 'subject' => env('VAPID_SUBJECT'), + 'public_key' => env('VAPID_PUBLIC_KEY'), + 'private_key' => env('VAPID_PRIVATE_KEY'), + 'pem_file' => env('VAPID_PEM_FILE'), + ], + + /* + * Google Cloud Messaging. + * Deprecated and optional. It's here only for compatibility reasons. + */ + 'gcm' => [ + 'key' => env('GCM_KEY'), + 'sender_id' => env('GCM_SENDER_ID'), + ], + + /* + * This is model that will be used to for push subscriptions. + */ + 'model' => \NotificationChannels\WebPush\PushSubscription::class, + + /* + * This is the name of the table that will be created by the migration and + * used by the PushSubscription model shipped with this package. + */ + 'table_name' => env('WEBPUSH_DB_TABLE', 'push_subscriptions'), + + /* + * This is the database connection that will be used by the migration and + * the PushSubscription model shipped with this package. + */ + 'database_connection' => env('WEBPUSH_DB_CONNECTION', env('DB_CONNECTION', 'mysql')), + +]; diff --git a/skolehjem/database/migrations/2020_11_30_142458_create_push_subscriptions_table.php b/skolehjem/database/migrations/2020_11_30_142458_create_push_subscriptions_table.php new file mode 100644 index 0000000..5e04162 --- /dev/null +++ b/skolehjem/database/migrations/2020_11_30_142458_create_push_subscriptions_table.php @@ -0,0 +1,38 @@ +charset ='utf8'; + $table->collation = 'utf8_unicode_ci'; + $table->increments('id'); + $table->morphs('subscribable'); + $table->string('endpoint', 500)->unique(); + $table->string('public_key')->nullable(); + $table->string('auth_token')->nullable(); + $table->string('content_encoding')->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::connection(config('webpush.database_connection'))->dropIfExists(config('webpush.table_name')); + } +} diff --git a/skolehjem/public/images/icons/appIcon.png b/skolehjem/public/images/icons/appIcon.png new file mode 100644 index 0000000..7ccf8ce Binary files /dev/null and b/skolehjem/public/images/icons/appIcon.png differ diff --git a/skolehjem/public/images/icons/appIcon.svg b/skolehjem/public/images/icons/appIcon.svg index d1a5787..3a10ff5 100644 --- a/skolehjem/public/images/icons/appIcon.svg +++ b/skolehjem/public/images/icons/appIcon.svg @@ -1 +1,2 @@ - \ No newline at end of file + + diff --git a/skolehjem/public/serviceWorkerCachedWebpags.js b/skolehjem/public/serviceWorkerCachedWebpags.js index 4c241a6..279db5c 100644 --- a/skolehjem/public/serviceWorkerCachedWebpags.js +++ b/skolehjem/public/serviceWorkerCachedWebpags.js @@ -30,20 +30,20 @@ const assets = [ // install event self.addEventListener('install', evt => { - //console.log('service worker installed'); + console.log('service worker installed'); evt.waitUntil( caches.open(staticCacheName).then((cache) => { //console.log('caching shell assets'); return cache.addAll(assets); }).catch((r) => { - console.log("I dont workkkkk"); + console.log("Install Fail"); }) ); }); // activate event self.addEventListener('activate', evt => { - //console.log('service worker activated'); + console.log('service worker activated'); evt.waitUntil( caches.keys().then(keys => { //console.log(keys); @@ -53,29 +53,11 @@ self.addEventListener('activate', evt => { ); }) ); + }); -// fetch event -/* self.addEventListener('fetch', evt => { console.log('fetch event'); - evt.respondWith( - caches.match(evt.request).then(async function (cacheRes) { - return cacheRes || fetch(evt.request).then(fetchRes => { - return caches.open(dynamicCacheName).then(cache => { - cache.put(evt.request.url, fetchRes.clone()).then(r => { - return fetchRes; - }); - }).catch((r) => { - console.log("I dont work"); - }); - }); - }) - ); -});*/ - -self.addEventListener('fetch', evt => { - console.log('fetch event', evt); evt.respondWith( caches.match(evt.request).then(cacheRes => { return cacheRes || fetch(evt.request).then(fetchRes => { @@ -90,53 +72,19 @@ self.addEventListener('fetch', evt => { ); }); -/* -self.addEventListener('fetch', evt => { - console.log("ARGHHHH"); - - if(navigator.onLine) { - evt.respondWith(async function() { - return fetch(evt.request).then((fetchRes) => { - caches.open(dynamicCacheName).then(cache => { - cache.put(evt.request.url, fetchRes.clone()); - }) - }) - }); - } else { - console.log('fetch event'); - evt.respondWith(async function () { - let cachedResponse = await caches.match(evt.request); - - if(cachedResponse) return cachedResponse; - else return caches.match("/offline.html"); - }); +self.addEventListener('push', function(event) { + if (!(self.Notification && self.Notification.permission === 'granted')) { + //notifications aren't supported or permission not granted! + return; } -});*/ - -/* -self.addEventListener('push', evt => { - const title = "Test Notification"; - const body = "Det her et en demo på hvordan en notification kan se ud! "; - const icon = "/icons/browserFavIcon.svg" - const tag = "simple-push-example-tag"; - evt.waitUntil( - self.registration.showNotification(title, { - body : body, - icon : icon, - tag : tag - }) - ); + if (event.data) { + let msg = event.data.json(); + console.log(msg) + event.waitUntil(self.registration.showNotification(msg.title, { + body: msg.body, + icon: msg.icon, + actions: msg.actions + })); + } }); - - - -function displayNotification(){ - if(Notification.permission === 'granted'){ - navigator.serviceWorker.getRegistration() - .then(function (reg){ - reg.showNotification('Helloe ') - }) - } -} -*/ diff --git a/skolehjem/public/serviceWorkerRegistration.js b/skolehjem/public/serviceWorkerRegistration.js index b9c8b65..f61c502 100644 --- a/skolehjem/public/serviceWorkerRegistration.js +++ b/skolehjem/public/serviceWorkerRegistration.js @@ -1,22 +1,56 @@ //Service Worker Registration - +let isSubscribed = false; +let swRegistration = null; +const applicationServerPublicKey = 'BHTLd76Yura3OIkZ52f4qh3G_i8RY3kvyOooVJXFVGle04JNW4d3JvwYQJ1JOZ9Y_uuZFsB_URqrlHQFhQ01V6M'; /* Make sure that we support service worker :) */ + if('serviceWorker' in navigator){ window.addEventListener('load', () => { navigator.serviceWorker .register('/serviceWorkerCachedWebpags.js') - .then(reg => console.log("Service Worker has been: registered")) + .then(reg => { + console.log("Service Worker registered") + swRegistration = reg; + + var serviceworker; + + if (reg.installing) + serviceworker = reg.installing; + else if (reg.waiting) + serviceworker = reg.waiting; + else if (reg.active) + serviceworker = reg.active; + + initializeUI(); + + if (serviceworker) { + console.log("sw current state", serviceworker.state); + if (serviceworker.state == "activated") { + subscribeUser(); + } + else { + serviceworker.addEventListener("statechange", function (e) { + console.log("service worker statechange: ", e.target.state); + if (e.target.state == "activated") { + subscribeUser(reg); + initializeUI(); + } + }); + } + } + }) .catch(err => console.log(`Service Worker error: ${err}`)) - }) + }); } -/* + + Notification.requestPermission().then(function(permission){ - console.log('Notification permission was:', permission) + console.log('Notification ', permission) }); @@ -25,4 +59,82 @@ if('caches' in window){ }else { console.log("This browser is some junk, it dosen't support caching :(") } -*/ + + + +//Push Notifications +const urlB64ToUint8Array = base64String => { + const padding = '='.repeat((4 - (base64String.length % 4)) % 4) + const base64 = (base64String + padding).replace(/\-/g, '+').replace(/_/g, '/') + const rawData = atob(base64) + const outputArray = new Uint8Array(rawData.length) + for (let i = 0; i < rawData.length; ++i) { + outputArray[i] = rawData.charCodeAt(i) + } + return outputArray +} + +function subscribeUser(reg) { + const applicationServerKey = urlB64ToUint8Array(applicationServerPublicKey); + reg.pushManager.subscribe({ + userVisibleOnly: true, + applicationServerKey: applicationServerKey + }) + .then(function(subscription) { + console.log('User is subscribed.'); + + updateSubscriptionOnServer(subscription); + + isSubscribed = true; + + }) + .catch(function(err) { + console.log('Failed to subscribe the user: ', err); + }); +} + + +function updateSubscriptionOnServer(subscription) { + storePushSubscription(subscription); + console.log(JSON.stringify(subscription)); +} + + +function initializeUI() { + // Set the initial subscription value + swRegistration.pushManager.getSubscription() + .then(function(subscription) { + isSubscribed = !(subscription === null); + + if (isSubscribed) { + console.log('User IS subscribed.'); + } else { + console.log('User is NOT subscribed.'); + } + + }); +} + + +function storePushSubscription(pushSubscription) { + const token = document.querySelector('meta[name=csrf-token]').getAttribute('content'); + + fetch('/push', { + method: 'POST', + body: JSON.stringify(pushSubscription), + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + 'X-CSRF-Token': token + } + }) + .then((res) => { + return res.json(); + }) + .then((res) => { + console.log(res) + }) + .catch((err) => { + console.log(err) + }); +} diff --git a/skolehjem/resources/views/admin/layout/base.blade.php b/skolehjem/resources/views/admin/layout/base.blade.php index 52bea41..3885bf6 100644 --- a/skolehjem/resources/views/admin/layout/base.blade.php +++ b/skolehjem/resources/views/admin/layout/base.blade.php @@ -82,6 +82,7 @@ } +