From 8f7becc58b38813d8d0a11760cfaae1a67eaf635 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Mon, 22 Jul 2024 03:04:04 -0600 Subject: [PATCH] Add push notification api endpoints --- .../Controllers/Api/ApiV1Dot1Controller.php | 62 +++++++++++++++++++ app/User.php | 46 ++++++++------ composer.json | 2 +- composer.lock | 41 ++++++------ routes/api.php | 6 ++ 5 files changed, 119 insertions(+), 38 deletions(-) diff --git a/app/Http/Controllers/Api/ApiV1Dot1Controller.php b/app/Http/Controllers/Api/ApiV1Dot1Controller.php index 9a47bb150..e6dfeadff 100644 --- a/app/Http/Controllers/Api/ApiV1Dot1Controller.php +++ b/app/Http/Controllers/Api/ApiV1Dot1Controller.php @@ -37,6 +37,7 @@ use Jenssegers\Agent\Agent; use League\Fractal; use League\Fractal\Serializer\ArraySerializer; use Mail; +use NotificationChannels\Expo\ExpoPushToken; class ApiV1Dot1Controller extends Controller { @@ -1008,4 +1009,65 @@ class ApiV1Dot1Controller extends Controller return $this->json($account, 200, $rateLimiting ? $limits : []); } + + public function getExpoPushNotifications(Request $request) + { + abort_if(! $request->user() || ! $request->user()->token(), 403); + abort_unless($request->user()->tokenCan('push'), 403); + + $user = $request->user(); + $res = [ + 'expo_token' => (bool) $user->expo_token, + 'notify_like' => (bool) $user->notify_like, + 'notify_follow' => (bool) $user->notify_follow, + 'notify_mention' => (bool) $user->notify_mention, + 'notify_comment' => (bool) $user->notify_comment, + ]; + + return $this->json($res); + } + + public function disableExpoPushNotifications(Request $request) + { + abort_if(! $request->user() || ! $request->user()->token(), 403); + abort_unless($request->user()->tokenCan('push'), 403); + abort_unless(config('services.expo.access_token') && strlen(config('services.expo.access_token')) > 10, 404, 'Push notifications are not supported on this server.'); + $request->user()->update([ + 'expo_token' => null, + ]); + + return $this->json(['expo_token' => null]); + } + + public function updateExpoPushNotifications(Request $request) + { + abort_if(! $request->user() || ! $request->user()->token(), 403); + abort_unless($request->user()->tokenCan('push'), 403); + abort_unless(config('services.expo.access_token') && strlen(config('services.expo.access_token')) > 10, 404, 'Push notifications are not supported on this server.'); + $this->validate($request, [ + 'expo_token' => ['required', ExpoPushToken::rule()], + 'notify_like' => 'sometimes', + 'notify_follow' => 'sometimes', + 'notify_mention' => 'sometimes', + 'notify_comment' => 'sometimes', + ]); + + $user = $request->user()->update([ + 'expo_token' => $request->input('expo_token'), + 'notify_like' => $request->has('notify_like') && $request->boolean('notify_like'), + 'notify_follow' => $request->has('notify_follow') && $request->boolean('notify_follow'), + 'notify_mention' => $request->has('notify_mention') && $request->boolean('notify_mention'), + 'notify_comment' => $request->has('notify_comment') && $request->boolean('notify_comment'), + ]); + + $res = [ + 'expo_token' => (bool) $request->user()->expo_token, + 'notify_like' => (bool) $request->user()->notify_like, + 'notify_follow' => (bool) $request->user()->notify_follow, + 'notify_mention' => (bool) $request->user()->notify_mention, + 'notify_comment' => (bool) $request->user()->notify_comment, + ]; + + return $this->json($res); + } } diff --git a/app/User.php b/app/User.php index 6ec31e969..022448109 100644 --- a/app/User.php +++ b/app/User.php @@ -2,32 +2,35 @@ namespace App; -use Laravel\Passport\HasApiTokens; -use Illuminate\Notifications\Notifiable; +use App\Services\AvatarService; +use App\Util\RateLimit\User as UserRateLimit; +use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Foundation\Auth\User as Authenticatable; -use App\Util\RateLimit\User as UserRateLimit; -use App\Services\AvatarService; -use Illuminate\Database\Eloquent\Factories\HasFactory; -use NotificationChannels\WebPush\HasPushSubscriptions; +use Illuminate\Notifications\Notifiable; +use Laravel\Passport\HasApiTokens; use NotificationChannels\Expo\ExpoPushToken; +use NotificationChannels\WebPush\HasPushSubscriptions; class User extends Authenticatable { - use Notifiable, SoftDeletes, HasApiTokens, UserRateLimit, HasFactory, HasPushSubscriptions; + use HasApiTokens, HasFactory, HasPushSubscriptions, Notifiable, SoftDeletes, UserRateLimit; /** * The attributes that should be mutated to dates. * * @var array */ - protected $casts = [ - 'deleted_at' => 'datetime', - 'email_verified_at' => 'datetime', - '2fa_setup_at' => 'datetime', - 'last_active_at' => 'datetime', - 'expo_token' => ExpoPushToken::class - ]; + protected function casts(): array + { + return [ + 'deleted_at' => 'datetime', + 'email_verified_at' => 'datetime', + '2fa_setup_at' => 'datetime', + 'last_active_at' => 'datetime', + 'expo_token' => ExpoPushToken::class, + ]; + } /** * The attributes that are mass assignable. @@ -42,7 +45,12 @@ class User extends Authenticatable 'app_register_ip', 'email_verified_at', 'last_active_at', - 'register_source' + 'register_source', + 'expo_token', + 'notify_like', + 'notify_follow', + 'notify_mention', + 'notify_comment', ]; /** @@ -54,7 +62,7 @@ class User extends Authenticatable 'email', 'password', 'is_admin', 'remember_token', 'email_verified_at', '2fa_enabled', '2fa_secret', '2fa_backup_codes', '2fa_setup_at', 'deleted_at', - 'updated_at' + 'updated_at', ]; public function profile() @@ -97,7 +105,7 @@ class User extends Authenticatable public function storageUsedKey() { - return 'profile:storage:used:' . $this->id; + return 'profile:storage:used:'.$this->id; } public function accountLog() @@ -112,8 +120,8 @@ class User extends Authenticatable public function avatarUrl() { - if(!$this->profile_id || $this->status) { - return config('app.url') . '/storage/avatars/default.jpg'; + if (! $this->profile_id || $this->status) { + return config('app.url').'/storage/avatars/default.jpg'; } return AvatarService::get($this->profile_id); diff --git a/composer.json b/composer.json index de544cb59..b97ec1187 100644 --- a/composer.json +++ b/composer.json @@ -19,7 +19,7 @@ "doctrine/dbal": "^3.0", "intervention/image": "^2.4", "jenssegers/agent": "^2.6", - "laravel-notification-channels/expo": "^1.3.0|^2.0", + "laravel-notification-channels/expo": "~1.3.0|~2.0.0", "laravel-notification-channels/webpush": "^8.0", "laravel/framework": "^11.0", "laravel/helpers": "^1.1", diff --git a/composer.lock b/composer.lock index 1f8509874..e6fd309e8 100644 --- a/composer.lock +++ b/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": "fbadeaf1fbbd9e0f64feaa1433ca7dd0", + "content-hash": "c055c4b1ba26004ab6951e9dba4b4508", "packages": [ { "name": "aws/aws-crt-php", @@ -2249,29 +2249,34 @@ }, { "name": "laravel-notification-channels/expo", - "version": "1.3.1", + "version": "v2.0.0", "source": { "type": "git", "url": "https://github.com/laravel-notification-channels/expo.git", - "reference": "d718a89dfc4997aba69b673f5db416ac833188e9" + "reference": "29d038b6409077ac4c671cc5587a4dc7986260b0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel-notification-channels/expo/zipball/d718a89dfc4997aba69b673f5db416ac833188e9", - "reference": "d718a89dfc4997aba69b673f5db416ac833188e9", + "url": "https://api.github.com/repos/laravel-notification-channels/expo/zipball/29d038b6409077ac4c671cc5587a4dc7986260b0", + "reference": "29d038b6409077ac4c671cc5587a4dc7986260b0", "shasum": "" }, "require": { "ext-json": "*", - "guzzlehttp/guzzle": "~6.0 || ~7.0", - "illuminate/notifications": "~6.0 || ~7.0 || ~8.0 || ~9.0 || ~10.0 || ~11.0", - "illuminate/support": "~6.0 || ~7.0 || ~8.0 || ~9.0 || ~10.0 || ~11.0", - "php": ">=7.4 || ^8.0 || ^8.1 || ^8.2 || ^8.3" + "guzzlehttp/guzzle": "^7.1", + "illuminate/contracts": "^11.0", + "illuminate/notifications": "^11.0", + "illuminate/support": "^11.0", + "php": "~8.3" }, "require-dev": { - "mockery/mockery": "^1.0", - "orchestra/testbench": "^6.18", - "phpunit/phpunit": "^8.0" + "larastan/larastan": "^2.0", + "laravel/pint": "^1.0", + "orchestra/testbench": "^9.0", + "phpunit/phpunit": "^11.0" + }, + "suggest": { + "ext-zlib": "Required for compressing payloads exceeding 1 KiB in size." }, "type": "library", "extra": { @@ -2292,19 +2297,19 @@ ], "authors": [ { - "name": "Nick Pratley", - "email": "nick@npratley.net", - "homepage": "https://npratley.net/", + "name": "Muhammed Sari", + "email": "muhammed@dive.be", + "homepage": "https://dive.be", "role": "Developer" } ], - "description": "Expo Notifications driver for Laravel", + "description": "Expo Notifications Channel for Laravel", "homepage": "https://github.com/laravel-notification-channels/expo", "support": { "issues": "https://github.com/laravel-notification-channels/expo/issues", - "source": "https://github.com/laravel-notification-channels/expo/tree/1.3.1" + "source": "https://github.com/laravel-notification-channels/expo/tree/v2.0.0" }, - "time": "2024-03-15T00:24:58+00:00" + "time": "2024-03-18T07:49:28+00:00" }, { "name": "laravel-notification-channels/webpush", diff --git a/routes/api.php b/routes/api.php index bb81af2d7..65ea86bb3 100644 --- a/routes/api.php +++ b/routes/api.php @@ -194,6 +194,12 @@ Route::group(['prefix' => 'api'], function() use($middleware) { Route::post('invite/admin/uc', 'AdminInviteController@apiUsernameCheck')->middleware('throttle:20,120'); Route::post('invite/admin/ec', 'AdminInviteController@apiEmailCheck')->middleware('throttle:10,1440'); }); + + Route::group(['prefix' => 'expo'], function() use($middleware) { + Route::get('push-notifications', 'Api\ApiV1Dot1Controller@getExpoPushNotifications')->middleware($middleware); + Route::post('push-notifications/update', 'Api\ApiV1Dot1Controller@updateExpoPushNotifications')->middleware($middleware); + Route::post('push-notifications/disable', 'Api\ApiV1Dot1Controller@disableExpoPushNotifications')->middleware($middleware); + }); }); Route::group(['prefix' => 'live'], function() use($middleware) {