From 20d9f8b890bf69f2e20ffacaa9955eb003942c2e Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Wed, 21 Sep 2022 05:34:39 -0600 Subject: [PATCH 01/10] Update LikeService --- app/Services/LikeService.php | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/app/Services/LikeService.php b/app/Services/LikeService.php index 0046f2f1a..63da4e47e 100644 --- a/app/Services/LikeService.php +++ b/app/Services/LikeService.php @@ -10,20 +10,53 @@ use App\Like; class LikeService { const CACHE_KEY = 'pf:services:likes:ids:'; + const CACHE_SET_KEY = 'pf:services:likes:set:'; public static function add($profileId, $statusId) { $key = self::CACHE_KEY . $profileId . ':' . $statusId; Cache::increment('pf:services:likes:count:'.$statusId); Cache::forget('pf:services:likes:liked_by:'.$statusId); + self::setAdd($profileId, $statusId); return Cache::put($key, true, 86400); } + public static function setAdd($profileId, $statusId) + { + if(self::setCount($profileId) > 400) { + if(config('database.redis.client') === 'phpredis') { + Redis::zpopmin(self::CACHE_SET_KEY . $id); + } + } + + return Redis::zadd(self::CACHE_SET_KEY . $profileId, $statusId, $statusId); + } + + public static function setCount($id) + { + return Redis::zcard(self::CACHE_SET_KEY . $id); + } + + public static function setRem($profileId, $val) + { + return Redis::zrem(self::CACHE_SET_KEY . $profileId, $val); + } + + public static function get($profileId, $start = 0, $stop = 10) + { + if($stop > 100) { + $stop = 100; + } + + return Redis::zrevrange(self::CACHE_SET_KEY . $profileId, $start, $stop); + } + public static function remove($profileId, $statusId) { $key = self::CACHE_KEY . $profileId . ':' . $statusId; Cache::decrement('pf:services:likes:count:'.$statusId); Cache::forget('pf:services:likes:liked_by:'.$statusId); + self::setRem($profileId, $statusId); return Cache::put($key, false, 86400); } From 364adb4387818711c04de26c463591d5e9067708 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Fri, 23 Sep 2022 01:35:42 -0600 Subject: [PATCH 02/10] Update ApiV1Controller, fix mute/block entities --- app/Http/Controllers/Api/ApiV1Controller.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/Api/ApiV1Controller.php b/app/Http/Controllers/Api/ApiV1Controller.php index e6f70bb95..eda28a1ca 100644 --- a/app/Http/Controllers/Api/ApiV1Controller.php +++ b/app/Http/Controllers/Api/ApiV1Controller.php @@ -895,7 +895,8 @@ class ApiV1Controller extends Controller }) ->filter(function($account) { return $account && isset($account['id']); - }); + }) + ->values(); return $this->json($blocked); } @@ -1757,7 +1758,8 @@ class ApiV1Controller extends Controller }) ->filter(function($account) { return $account && isset($account['id']); - }); + }) + ->values(); return $this->json($mutes); } From 7685e868dbf22d79175850af237a576658119fea Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Fri, 23 Sep 2022 01:36:18 -0600 Subject: [PATCH 03/10] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 768af7f21..f8f7e1602 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -83,6 +83,7 @@ - Update ApiV1Controller, fix pagination header. Fixes #3354 ([4fe07e6f](https://github.com/pixelfed/pixelfed/commit/4fe07e6f)) - Update ApiV1Controller, add optional place_id parameter to POST /api/v1/statuses endpoint ([ef0d1f84](https://github.com/pixelfed/pixelfed/commit/ef0d1f84)) - Update SettingsController, fix double json encoding and cache settings for 7 days ([4514ab1d](https://github.com/pixelfed/pixelfed/commit/4514ab1d)) +- Update ApiV1Controller, fix mute/block entities ([364adb43](https://github.com/pixelfed/pixelfed/commit/364adb43)) - ([](https://github.com/pixelfed/pixelfed/commit/)) ## [v0.11.3 (2022-05-09)](https://github.com/pixelfed/pixelfed/compare/v0.11.2...v0.11.3) From d06fac072c812e40b155cda9d4781adbf0a3e48e Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Sat, 24 Sep 2022 18:07:24 -0600 Subject: [PATCH 04/10] Update ApiV1Controller, fix mute/blocks orderBy --- app/Http/Controllers/Api/ApiV1Controller.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/Http/Controllers/Api/ApiV1Controller.php b/app/Http/Controllers/Api/ApiV1Controller.php index eda28a1ca..42b5e6121 100644 --- a/app/Http/Controllers/Api/ApiV1Controller.php +++ b/app/Http/Controllers/Api/ApiV1Controller.php @@ -888,6 +888,7 @@ class ApiV1Controller extends Controller ->whereUserId($user->profile_id) ->whereFilterableType('App\Profile') ->whereFilterType('block') + ->orderByDesc('id') ->simplePaginate($limit) ->pluck('filterable_id') ->map(function($id) { @@ -1751,6 +1752,7 @@ class ApiV1Controller extends Controller $mutes = UserFilter::whereUserId($user->profile_id) ->whereFilterableType('App\Profile') ->whereFilterType('mute') + ->orderByDesc('id') ->simplePaginate($limit) ->pluck('filterable_id') ->map(function($id) { From 491843ac6cdb0d9220ff03d1aaaaae1f10791009 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Sat, 24 Sep 2022 20:52:19 -0600 Subject: [PATCH 05/10] Update v1.1 api --- .../Controllers/Api/ApiV1Dot1Controller.php | 154 ++++++++++++++++++ routes/api.php | 12 +- 2 files changed, 164 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/Api/ApiV1Dot1Controller.php b/app/Http/Controllers/Api/ApiV1Dot1Controller.php index 75bd2b3e9..429c9211c 100644 --- a/app/Http/Controllers/Api/ApiV1Dot1Controller.php +++ b/app/Http/Controllers/Api/ApiV1Dot1Controller.php @@ -3,17 +3,21 @@ namespace App\Http\Controllers\Api; use Cache; +use DB; use App\Http\Controllers\Controller; use Illuminate\Http\Request; use League\Fractal; use League\Fractal\Serializer\ArraySerializer; use League\Fractal\Pagination\IlluminatePaginatorAdapter; +use App\AccountLog; +use App\EmailVerification; use App\Status; use App\Report; use App\Profile; use App\Services\AccountService; use App\Services\StatusService; use App\Services\ProfileStatusService; +use Jenssegers\Agent\Agent; class ApiV1Dot1Controller extends Controller { @@ -204,4 +208,154 @@ class ApiV1Dot1Controller extends Controller return $this->json($res); } + + /** + * POST /api/v1.1/accounts/change-password + * + * @return \App\Transformer\Api\AccountTransformer + */ + public function accountChangePassword(Request $request) + { + $user = $request->user(); + abort_if(!$user, 403); + abort_if($user->status != null, 403); + + $this->validate($request, [ + 'current_password' => 'bail|required|current_password', + 'new_password' => 'required|min:' . config('pixelfed.min_password_length', 8), + 'confirm_password' => 'required|same:new_password' + ],[ + 'current_password' => 'The password you entered is incorrect' + ]); + + $user->password = bcrypt($request->input('new_password')); + $user->save(); + + return $this->json(AccountService::get($user->profile_id)); + } + + /** + * GET /api/v1.1/accounts/login-activity + * + * @return array + */ + public function accountLoginActivity(Request $request) + { + $user = $request->user(); + abort_if(!$user, 403); + abort_if($user->status != null, 403); + $agent = new Agent(); + + $activity = AccountLog::whereUserId($user->id) + ->whereAction('auth.login') + ->orderBy('created_at', 'desc') + ->limit(10) + ->get() + ->map(function($item) use($agent) { + $agent->setUserAgent($item->user_agent); + return [ + 'id' => $item->id, + 'action' => $item->action, + 'ip' => $item->ip_address, + 'is_mobile' => $agent->isMobile(), + 'device' => $agent->device(), + 'browser' => $agent->browser(), + 'platform' => $agent->platform(), + 'created_at' => $item->created_at->format('c') + ]; + }); + + return $this->json($activity); + } + + /** + * GET /api/v1.1/accounts/two-factor + * + * @return array + */ + public function accountTwoFactor(Request $request) + { + $user = $request->user(); + abort_if(!$user, 403); + abort_if($user->status != null, 403); + + $res = [ + 'active' => (bool) $user->{'2fa_enabled'}, + 'setup_at' => $user->{'2fa_setup_at'} + ]; + return $this->json($res); + } + + /** + * GET /api/v1.1/accounts/emails-from-pixelfed + * + * @return array + */ + public function accountEmailsFromPixelfed(Request $request) + { + $user = $request->user(); + abort_if(!$user, 403); + abort_if($user->status != null, 403); + + $emailVerifications = EmailVerification::whereUserId($user->id) + ->orderByDesc('id') + ->where('created_at', '>', now()->subDays(14)) + ->limit(10) + ->get() + ->map(function($mail) { + return [ + 'type' => 'Email Verification', + 'created_at' => $mail->created_at->format('c') + ]; + }) + ->toArray(); + + $passwordResets = DB::table('password_resets') + ->whereEmail($user->email) + ->where('created_at', '>', now()->subDays(14)) + ->orderByDesc('created_at') + ->limit(10) + ->get() + ->map(function($mail) { + return [ + 'type' => 'Password Reset', + 'created_at' => now()->parse($mail->created_at)->format('c') + ]; + }) + ->toArray(); + + $res = [ + 'email_verifications' => $emailVerifications, + 'password_resets' => $passwordResets + ]; + + return $this->json($res); + } + + + /** + * GET /api/v1.1/accounts/apps-and-applications + * + * @return array + */ + public function accountApps(Request $request) + { + $user = $request->user(); + abort_if(!$user, 403); + abort_if($user->status != null, 403); + + $res = $user->tokens->map(function($token, $key) { + return [ + 'id' => $key + 1, + 'did' => encrypt($token->id), + 'name' => $token->name, + 'scopes' => $token->scopes, + 'revoked' => $token->revoked, + 'created_at' => $token->created_at, + 'expires_at' => $token->expires_at + ]; + }); + + return $this->json($res); + } } diff --git a/routes/api.php b/routes/api.php index cc147aff5..4ba95cdb8 100644 --- a/routes/api.php +++ b/routes/api.php @@ -99,8 +99,16 @@ Route::group(['prefix' => 'api'], function() use($middleware) { Route::group(['prefix' => 'v1.1'], function() use($middleware) { Route::post('report', 'Api\ApiV1Dot1Controller@report')->middleware($middleware); - Route::delete('accounts/avatar', 'Api\ApiV1Dot1Controller@deleteAvatar')->middleware($middleware); - Route::get('accounts/{id}/posts', 'Api\ApiV1Dot1Controller@accountPosts')->middleware($middleware); + + Route::group(['prefix' => 'accounts'], function () use($middleware) { + Route::delete('avatar', 'Api\ApiV1Dot1Controller@deleteAvatar')->middleware($middleware); + Route::get('{id}/posts', 'Api\ApiV1Dot1Controller@accountPosts')->middleware($middleware); + Route::post('change-password', 'Api\ApiV1Dot1Controller@accountChangePassword')->middleware($middleware); + Route::get('login-activity', 'Api\ApiV1Dot1Controller@accountLoginActivity')->middleware($middleware); + Route::get('two-factor', 'Api\ApiV1Dot1Controller@accountTwoFactor')->middleware($middleware); + Route::get('emails-from-pixelfed', 'Api\ApiV1Dot1Controller@accountEmailsFromPixelfed')->middleware($middleware); + Route::get('apps-and-applications', 'Api\ApiV1Dot1Controller@accountApps')->middleware($middleware); + }); Route::group(['prefix' => 'direct'], function () use($middleware) { Route::get('thread', 'DirectMessageController@thread')->middleware($middleware); From 78d82c7c2cea7a950dd87961f18b39d45d6f4edb Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Sat, 24 Sep 2022 22:31:17 -0600 Subject: [PATCH 06/10] Update v1.1 api --- .../Controllers/Api/ApiV1Dot1Controller.php | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/app/Http/Controllers/Api/ApiV1Dot1Controller.php b/app/Http/Controllers/Api/ApiV1Dot1Controller.php index 429c9211c..3971997c9 100644 --- a/app/Http/Controllers/Api/ApiV1Dot1Controller.php +++ b/app/Http/Controllers/Api/ApiV1Dot1Controller.php @@ -18,6 +18,8 @@ use App\Services\AccountService; use App\Services\StatusService; use App\Services\ProfileStatusService; use Jenssegers\Agent\Agent; +use Mail; +use App\Mail\PasswordChange; class ApiV1Dot1Controller extends Controller { @@ -231,6 +233,19 @@ class ApiV1Dot1Controller extends Controller $user->password = bcrypt($request->input('new_password')); $user->save(); + $log = new AccountLog; + $log->user_id = $user->id; + $log->item_id = $user->id; + $log->item_type = 'App\User'; + $log->action = 'account.edit.password'; + $log->message = 'Password changed'; + $log->link = null; + $log->ip_address = $request->ip(); + $log->user_agent = $request->userAgent(); + $log->save(); + + Mail::to($request->user())->send(new PasswordChange($user)); + return $this->json(AccountService::get($user->profile_id)); } @@ -324,9 +339,24 @@ class ApiV1Dot1Controller extends Controller }) ->toArray(); + $passwordChanges = AccountLog::whereUserId($user->id) + ->whereAction('account.edit.password') + ->where('created_at', '>', now()->subDays(14)) + ->orderByDesc('created_at') + ->limit(10) + ->get() + ->map(function($mail) { + return [ + 'type' => 'Password Change', + 'created_at' => $mail->created_at + ]; + }) + ->toArray(); + $res = [ 'email_verifications' => $emailVerifications, - 'password_resets' => $passwordResets + 'password_resets' => $passwordResets, + 'password_changes' => $passwordChanges ]; return $this->json($res); From 613e98ce097dd130357157e55cd3116886a2b6eb Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Sat, 24 Sep 2022 23:20:45 -0600 Subject: [PATCH 07/10] Update v1.1 api --- app/Http/Controllers/Api/ApiV1Dot1Controller.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/Http/Controllers/Api/ApiV1Dot1Controller.php b/app/Http/Controllers/Api/ApiV1Dot1Controller.php index 3971997c9..66474e145 100644 --- a/app/Http/Controllers/Api/ApiV1Dot1Controller.php +++ b/app/Http/Controllers/Api/ApiV1Dot1Controller.php @@ -260,18 +260,20 @@ class ApiV1Dot1Controller extends Controller abort_if(!$user, 403); abort_if($user->status != null, 403); $agent = new Agent(); + $currentIp = $request->ip(); $activity = AccountLog::whereUserId($user->id) ->whereAction('auth.login') ->orderBy('created_at', 'desc') ->limit(10) ->get() - ->map(function($item) use($agent) { + ->map(function($item) use($agent, $currentIp) { $agent->setUserAgent($item->user_agent); return [ 'id' => $item->id, 'action' => $item->action, 'ip' => $item->ip_address, + 'ip_current' => $item->ip_address === $currentIp, 'is_mobile' => $agent->isMobile(), 'device' => $agent->device(), 'browser' => $agent->browser(), From 34b57783c46d44b059098a36d758d7f3ed53e0ec Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Sat, 24 Sep 2022 23:38:08 -0600 Subject: [PATCH 08/10] Update v1.1 api --- app/Http/Controllers/Api/ApiV1Dot1Controller.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/Http/Controllers/Api/ApiV1Dot1Controller.php b/app/Http/Controllers/Api/ApiV1Dot1Controller.php index 66474e145..7dff38cbc 100644 --- a/app/Http/Controllers/Api/ApiV1Dot1Controller.php +++ b/app/Http/Controllers/Api/ApiV1Dot1Controller.php @@ -265,6 +265,7 @@ class ApiV1Dot1Controller extends Controller $activity = AccountLog::whereUserId($user->id) ->whereAction('auth.login') ->orderBy('created_at', 'desc') + ->groupBy('ip_address') ->limit(10) ->get() ->map(function($item) use($agent, $currentIp) { From e362ef9ef980f4b6601da355fab493b3226c5513 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Sun, 25 Sep 2022 01:14:20 -0600 Subject: [PATCH 09/10] Update atom feed, remove invalid entities --- resources/views/atom/user.blade.php | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/resources/views/atom/user.blade.php b/resources/views/atom/user.blade.php index 219c11ce4..792dd7466 100644 --- a/resources/views/atom/user.blade.php +++ b/resources/views/atom/user.blade.php @@ -7,20 +7,14 @@ {{$profile['username']}} on Pixelfed {{$profile['note']}} {{$profile['created_at']}} - - {{$profile['url']}} {{$profile['url']}} {{$profile['url']}} - {{$profile['note']}} - - -@foreach($items as $item) - - {{ strip_tags($item['content']) }} +@foreach($items as $item) + {{ $item['content'] ? strip_tags($item['content']) : "No caption" }} {{ $item['url'] }} From d221600c72c5ae8efbbad726ee8dd361fcc40868 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Sun, 25 Sep 2022 01:14:47 -0600 Subject: [PATCH 10/10] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f8f7e1602..1c893644b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -84,6 +84,7 @@ - Update ApiV1Controller, add optional place_id parameter to POST /api/v1/statuses endpoint ([ef0d1f84](https://github.com/pixelfed/pixelfed/commit/ef0d1f84)) - Update SettingsController, fix double json encoding and cache settings for 7 days ([4514ab1d](https://github.com/pixelfed/pixelfed/commit/4514ab1d)) - Update ApiV1Controller, fix mute/block entities ([364adb43](https://github.com/pixelfed/pixelfed/commit/364adb43)) +- Update atom feed, remove invalid entities ([e362ef9e](https://github.com/pixelfed/pixelfed/commit/e362ef9e)) - ([](https://github.com/pixelfed/pixelfed/commit/)) ## [v0.11.3 (2022-05-09)](https://github.com/pixelfed/pixelfed/compare/v0.11.2...v0.11.3)