Skip to content

Commit 9f1c2f6

Browse files
authored
Merge branch 'master' into local-cache-manager-config
2 parents 02ddb46 + 185cabd commit 9f1c2f6

File tree

152 files changed

+1741
-911
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

152 files changed

+1741
-911
lines changed

Diff for: .env.example

+13-10
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ CLIENT_CHECK_VERSION=false
265265
# NOTIFICATION_CLEANUP_MAX_DELETE=50000
266266

267267
# The open source bounty info page/form url
268-
#OS_BOUNTY_URL=http://example.com/bounty_form
268+
# OS_BOUNTY_URL=http://example.com/bounty_form
269269

270270
# OAUTH_MAX_USER_CLIENTS=1
271271

@@ -292,16 +292,16 @@ CLIENT_CHECK_VERSION=false
292292
# PAGINATION_MAX_COUNT=10000
293293

294294
## Limits for the allowed number of simultaneous beatmapset uploads (displayed on the support page: /home/support)
295-
#BEATMAPSET_UPLOAD_ALLOWED=4
296-
#BEATMAPSET_UPLOAD_BONUS_PER_RANKED=1
297-
#BEATMAPSET_UPLOAD_BONUS_PER_RANKED_MAX=2
298-
#BEATMAPSET_UPLOAD_ALLOWED_SUPPORTER=8
299-
#BEATMAPSET_UPLOAD_BONUS_PER_RANKED_SUPPORTER=1
300-
#BEATMAPSET_UPLOAD_BONUS_PER_RANKED_MAX_SUPPORTER=12
295+
# BEATMAPSET_UPLOAD_ALLOWED=4
296+
# BEATMAPSET_UPLOAD_BONUS_PER_RANKED=1
297+
# BEATMAPSET_UPLOAD_BONUS_PER_RANKED_MAX=2
298+
# BEATMAPSET_UPLOAD_ALLOWED_SUPPORTER=8
299+
# BEATMAPSET_UPLOAD_BONUS_PER_RANKED_SUPPORTER=1
300+
# BEATMAPSET_UPLOAD_BONUS_PER_RANKED_MAX_SUPPORTER=12
301301

302-
#RECAPTCHA_SECRET=
303-
#RECAPTCHA_SITEKEY=
304-
#RECAPTCHA_THRESHOLD=
302+
# RECAPTCHA_SECRET=
303+
# RECAPTCHA_SITEKEY=
304+
# RECAPTCHA_THRESHOLD=
305305

306306
# TWITCH_CLIENT_ID=
307307
# TWITCH_CLIENT_SECRET=
@@ -336,3 +336,6 @@ CLIENT_CHECK_VERSION=false
336336

337337
# USER_COUNTRY_CHANGE_MAX_MIXED_MONTHS=2
338338
# USER_COUNTRY_CHANGE_MIN_MONTHS=6
339+
340+
# USER_INACTIVE_DAYS_VERIFICATION=180
341+
# USER_INACTIVE_FORCE_PASSWORD_RESET=false

Diff for: app/Http/Controllers/AccountController.php

+8-5
Original file line numberDiff line numberDiff line change
@@ -84,16 +84,19 @@ public function avatar()
8484

8585
public function cover()
8686
{
87-
$user = auth()->user();
87+
$user = \Auth::user();
88+
$params = get_params(\Request::all(), null, [
89+
'cover_file:file',
90+
'cover_id:int',
91+
], ['null_missing' => true]);
8892

89-
if (Request::hasFile('cover_file') && !$user->osu_subscriber) {
93+
if ($params['cover_file'] !== null && !$user->osu_subscriber) {
9094
return error_popup(osu_trans('errors.supporter_only'));
9195
}
9296

9397
try {
94-
$profile = $user->profileCustomization();
95-
$profile->cover()->set(Request::input('cover_id'), Request::file('cover_file'));
96-
$profile->save();
98+
$user->cover()->set($params['cover_id'], $params['cover_file']);
99+
$user->save();
97100
} catch (ImageProcessorException $e) {
98101
return error_popup($e->getMessage());
99102
}

Diff for: app/Http/Controllers/BeatmapsController.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ private static function beatmapScores(string $id, ?string $scoreTransformerType,
7575
'type' => $type,
7676
'user' => $currentUser,
7777
]);
78-
$scores = $esFetch->all()->loadMissing(['beatmap', 'user.country', 'user.userProfileCustomization']);
78+
$scores = $esFetch->all()->loadMissing(['beatmap', 'user.country']);
7979
$userScore = $esFetch->userBest();
8080
$scoreTransformer = new ScoreTransformer($scoreTransformerType);
8181

Diff for: app/Http/Controllers/Forum/TopicsController.php

+3-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use App\Models\Forum\TopicCover;
1717
use App\Models\Forum\TopicPoll;
1818
use App\Models\Forum\TopicWatch;
19+
use App\Models\UserProfileCustomization;
1920
use App\Transformers\Forum\TopicCoverTransformer;
2021
use Auth;
2122
use DB;
@@ -427,6 +428,7 @@ public function show($id)
427428

428429
$pollSummary = PollOption::summary($topic, $currentUser);
429430

431+
$topic->incrementViewCount($currentUser, \Request::ip());
430432
$posts->last()->markRead($currentUser);
431433

432434
$coverModel = $topic->cover ?? new TopicCover();
@@ -625,7 +627,7 @@ private function getIndexParams($topic, $currentUser, $userCanModerate)
625627
$params['limit'] = clamp($params['limit'] ?? 20, 1, 50);
626628

627629
if ($userCanModerate) {
628-
$params['with_deleted'] = $params['with_deleted'] ?? $currentUser->profileCustomization()->forum_posts_show_deleted;
630+
$params['with_deleted'] ??= ($currentUser->userProfileCustomization ?? UserProfileCustomization::DEFAULTS)['forum_posts_show_deleted'];
629631
} else {
630632
$params['with_deleted'] = false;
631633
}

Diff for: app/Http/Controllers/RankingController.php

+1-7
Original file line numberDiff line numberDiff line change
@@ -197,10 +197,6 @@ public function index($mode, $type)
197197
if (isset($forceIndex)) {
198198
$stats->from(DB::raw("{$table} FORCE INDEX ($forceIndex)"));
199199
}
200-
201-
if (is_api_request()) {
202-
$stats->with(['user.userProfileCustomization']);
203-
}
204200
}
205201

206202
$maxResults = $this->maxResults($modeInt, $stats);
@@ -304,13 +300,11 @@ public function spotlight($mode)
304300
}
305301

306302
if (is_api_request()) {
307-
$scores = $scores->with(['user.userProfileCustomization'])->get();
308-
309303
return [
310304
// transformer can't do nested includes with params properly.
311305
// https://github.com/thephpleague/fractal/issues/239
312306
'beatmapsets' => json_collection($beatmapsets, 'Beatmapset', ['beatmaps']),
313-
'ranking' => json_collection($scores, 'UserStatistics', ['user', 'user.cover', 'user.country']),
307+
'ranking' => json_collection($scores->get(), 'UserStatistics', ['user', 'user.cover', 'user.country']),
314308
'spotlight' => json_item($spotlight, 'Spotlight', ["participant_count:mode({$mode})"]),
315309
];
316310
} else {

Diff for: app/Http/Controllers/ScorePinsController.php

+9-2
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,16 @@ public function store()
9191
$rulesetId = Beatmap::MODES[$score->getMode()];
9292
$currentMinDisplayOrder = $user->scorePins()->where('ruleset_id', $rulesetId)->min('display_order') ?? 2500;
9393

94+
$soloScore = $score instanceof Solo\Score
95+
? $score
96+
: Solo\Score::firstWhere(['ruleset_id' => $rulesetId, 'legacy_score_id' => $score->getKey()]);
97+
9498
try {
95-
(new ScorePin(['display_order' => $currentMinDisplayOrder - 100, 'ruleset_id' => $rulesetId]))
96-
->user()->associate($user)
99+
(new ScorePin([
100+
'display_order' => $currentMinDisplayOrder - 100,
101+
'ruleset_id' => $rulesetId,
102+
'new_score_id' => $soloScore?->getKey(),
103+
]))->user()->associate($user)
97104
->score()->associate($score)
98105
->saveOrExplode();
99106
} catch (Exception $ex) {

Diff for: app/Http/Controllers/ScoresController.php

+26-16
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@
77

88
use App\Models\Score\Best\Model as ScoreBest;
99
use App\Models\Solo\Score as SoloScore;
10-
use App\Models\UserCountryHistory;
1110
use App\Transformers\ScoreTransformer;
1211
use App\Transformers\UserCompactTransformer;
13-
use Carbon\CarbonImmutable;
1412

1513
class ScoresController extends Controller
1614
{
15+
const REPLAY_DOWNLOAD_COUNT_INTERVAL = 86400; // 1 day
16+
1717
public function __construct()
1818
{
1919
parent::__construct();
@@ -52,20 +52,30 @@ public function download($rulesetOrSoloId, $id = null)
5252
abort(404);
5353
}
5454

55-
if (\Auth::user()->getKey() !== $score->user_id) {
56-
$score->user->statistics($score->getMode(), true)->increment('replay_popularity');
57-
58-
$month = CarbonImmutable::now();
59-
$currentMonth = UserCountryHistory::formatDate($month);
60-
61-
$score->user->replaysWatchedCounts()
62-
->firstOrCreate(['year_month' => $currentMonth], ['count' => 0])
63-
->incrementInstance('count');
64-
65-
if ($score instanceof ScoreBest) {
66-
$score->replayViewCount()
67-
->firstOrCreate([], ['play_count' => 0])
68-
->incrementInstance('play_count');
55+
$currentUser = \Auth::user();
56+
if (
57+
!$currentUser->isRestricted()
58+
&& $currentUser->getKey() !== $score->user_id
59+
&& ($currentUser->token()?->client->password_client ?? false)
60+
) {
61+
$countLock = \Cache::lock(
62+
"view:score_replay:{$score->getKey()}:{$currentUser->getKey()}",
63+
static::REPLAY_DOWNLOAD_COUNT_INTERVAL,
64+
);
65+
66+
if ($countLock->get()) {
67+
$score->user->statistics($score->getMode(), true)->increment('replay_popularity');
68+
69+
$currentMonth = format_month_column(new \DateTime());
70+
$score->user->replaysWatchedCounts()
71+
->firstOrCreate(['year_month' => $currentMonth], ['count' => 0])
72+
->incrementInstance('count');
73+
74+
if ($score instanceof ScoreBest) {
75+
$score->replayViewCount()
76+
->firstOrCreate([], ['play_count' => 0])
77+
->incrementInstance('play_count');
78+
}
6979
}
7080
}
7181

Diff for: app/Http/Controllers/SessionsController.php

+2
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ public function store()
7777
$forceReactivation = new ForceReactivation($user, $request);
7878

7979
if ($forceReactivation->isRequired()) {
80+
DatadogLoginAttempt::log('password_reset');
8081
$forceReactivation->run();
8182

8283
\Session::flash('password_reset_start', [
@@ -87,6 +88,7 @@ public function store()
8788
return ujs_redirect(route('password-reset'));
8889
}
8990

91+
DatadogLoginAttempt::log(null);
9092
$this->login($user, $remember);
9193

9294
return [

Diff for: app/Http/Controllers/UserCoverPresetsController.php

+87
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<?php
2+
3+
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the GNU Affero General Public License v3.0.
4+
// See the LICENCE file in the repository root for full licence text.
5+
6+
namespace App\Http\Controllers;
7+
8+
use App\Models\UserCoverPreset;
9+
use Symfony\Component\HttpFoundation\Response;
10+
11+
class UserCoverPresetsController extends Controller
12+
{
13+
public function __construct()
14+
{
15+
$this->middleware('auth');
16+
17+
parent::__construct();
18+
}
19+
20+
public function batchActivate(): Response
21+
{
22+
$params = get_params(\Request::all(), null, [
23+
'ids:int[]',
24+
'active:bool',
25+
]);
26+
if (!isset($params['active'])) {
27+
abort(422, 'parameter "active" is missing');
28+
}
29+
UserCoverPreset::whereKey($params['ids'] ?? [])->update(['active' => $params['active']]);
30+
31+
return response(null, 204);
32+
}
33+
34+
public function index(): Response
35+
{
36+
priv_check('UserCoverPresetManage')->ensureCan();
37+
38+
return ext_view('user_cover_presets.index', [
39+
'items' => UserCoverPreset::orderBy('id', 'ASC')->get(),
40+
]);
41+
}
42+
43+
public function store(): Response
44+
{
45+
priv_check('UserCoverPresetManage')->ensureCan();
46+
47+
try {
48+
$files = \Request::file('files') ?? [];
49+
foreach ($files as $file) {
50+
$item = \DB::transaction(function () use ($file) {
51+
$item = UserCoverPreset::create();
52+
$item->file()->store($file->getRealPath());
53+
$item->saveOrExplode();
54+
55+
return $item;
56+
});
57+
$hash ??= "#cover-{$item->getKey()}";
58+
}
59+
\Session::flash('popup', osu_trans('user_cover_presets.store.ok'));
60+
} catch (\Throwable $e) {
61+
\Session::flash('popup', osu_trans('user_cover_presets.store.failed', ['error' => $e->getMessage()]));
62+
}
63+
64+
return ujs_redirect(route('user-cover-presets.index').($hash ?? ''));
65+
}
66+
67+
public function update(string $id): Response
68+
{
69+
priv_check('UserCoverPresetManage')->ensureCan();
70+
71+
$item = UserCoverPreset::findOrFail($id);
72+
$params = get_params(\Request::all(), null, [
73+
'file:file',
74+
'active:bool',
75+
], ['null_missing' => true]);
76+
77+
if ($params['file'] !== null) {
78+
$item->file()->store($params['file']);
79+
$item->save();
80+
}
81+
if ($params['active'] !== null) {
82+
$item->update(['active' => $params['active']]);
83+
}
84+
85+
return ujs_redirect(route('user-cover-presets.index').'#cover-'.$item->getKey());
86+
}
87+
}

Diff for: app/Http/Controllers/UsersController.php

-2
Original file line numberDiff line numberDiff line change
@@ -665,8 +665,6 @@ public function show($id, $mode = null)
665665
} else {
666666
$achievements = json_collection(app('medals')->all(), 'Achievement');
667667

668-
$extras = [];
669-
670668
$initialData = [
671669
'achievements' => $achievements,
672670
'current_mode' => $currentMode,

Diff for: app/Jobs/Notifications/BeatmapsetDiscussionQualifiedProblem.php

+8-8
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,16 @@ public function getListeningUserIds(): array
2929

3030
$ids = [];
3131

32-
$notificationOptions = UserNotificationOption
32+
UserNotificationOption
3333
::where(['name' => Notification::BEATMAPSET_DISCUSSION_QUALIFIED_PROBLEM])
3434
->whereNotNull('details')
35-
->get();
36-
37-
foreach ($notificationOptions as $notificationOption) {
38-
if (count(array_intersect($notificationOption->details['modes'] ?? [], $modes)) > 0) {
39-
$ids[] = $notificationOption->user_id;
40-
}
41-
}
35+
->chunkById(1000, function ($options) use (&$ids, $modes) {
36+
foreach ($options as $option) {
37+
if (count(array_intersect($option->details['modes'] ?? [], $modes)) > 0) {
38+
$ids[] = $option->user_id;
39+
}
40+
}
41+
});
4242

4343
return $ids;
4444
}

Diff for: app/Jobs/Notifications/BeatmapsetDisqualify.php

+8-9
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,15 @@ public function getListeningUserIds(): array
2020
return Beatmap::modeStr($modeInt);
2121
}, $modes);
2222

23-
$notificationOptions = UserNotificationOption
24-
::where(['name' => Notification::BEATMAPSET_DISQUALIFY])
23+
UserNotificationOption::where(['name' => Notification::BEATMAPSET_DISQUALIFY])
2524
->whereNotNull('details')
26-
->get();
27-
28-
foreach ($notificationOptions as $notificationOption) {
29-
if (count(array_intersect($notificationOption->details['modes'] ?? [], $modes)) > 0) {
30-
$ids[] = $notificationOption->user_id;
31-
}
32-
}
25+
->chunkById(1000, function ($options) use (&$ids, $modes) {
26+
foreach ($options as $option) {
27+
if (count(array_intersect($option->details['modes'] ?? [], $modes)) > 0) {
28+
$ids[] = $option->user_id;
29+
}
30+
}
31+
});
3332

3433
return $ids;
3534
}

Diff for: app/Libraries/CommentBundleParams.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public function __construct(array $params, ?User $user)
3636
$this->cursor = null;
3737
$this->limit = static::DEFAULT_LIMIT;
3838
$this->page = static::DEFAULT_PAGE;
39-
$this->sort = optional($user)->profileCustomization()->comments_sort ?? null;
39+
$this->sort = $user->userProfileCustomization->comments_sort ?? null;
4040

4141
$this->setAll($params);
4242
}

0 commit comments

Comments
 (0)