Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into score-solo-index
Browse files Browse the repository at this point in the history
  • Loading branch information
nanaya committed Jun 21, 2023
2 parents 5234708 + e3266f1 commit 5aba3d3
Show file tree
Hide file tree
Showing 1,543 changed files with 17,224 additions and 8,768 deletions.
4 changes: 2 additions & 2 deletions .env.dusk.local.example
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
APP_KEY=
APP_ENV=testing

APP_URL=http://nginx
NOTIFICATION_ENDPOINT=/home/notifications/feed-dusk
APP_URL=http://localhost:8000
NOTIFICATION_ENDPOINT=ws://notification-server-dusk:2345

DB_DATABASE=osu_test
DB_DATABASE_CHAT=osu_chat_test
Expand Down
10 changes: 9 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -251,8 +251,16 @@ CLIENT_CHECK_VERSION=false

# OAUTH_MAX_USER_CLIENTS=1

# USER_REPORT_NOTIFICATION_ENDPOINT_MODERATION=
# USER_REPORT_NOTIFICATION_ENDPOINT_CHEATING=
# default if nothing specified for specific type
# USER_REPORT_NOTIFICATION_ENDPOINT_MODERATION=

# USER_REPORT_NOTIFICATION_ENDPOINT_BEATMAPSET=
# USER_REPORT_NOTIFICATION_ENDPOINT_BEATMAPSET_DISCUSSION=
# USER_REPORT_NOTIFICATION_ENDPOINT_CHAT=
# USER_REPORT_NOTIFICATION_ENDPOINT_COMMENT=
# USER_REPORT_NOTIFICATION_ENDPOINT_FORUM=
# USER_REPORT_NOTIFICATION_ENDPOINT_USER=

# LOG_CHANNEL=single

Expand Down
4 changes: 3 additions & 1 deletion .env.testing.example
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
DB_DATABASE=osu_test
DB_DATABASE_CHAT=osu_chat_test
DB_DATABASE_MP=osu_mp_test
DB_DATABASE_STORE=osu_store_test
DB_DATABASE_UPDATES=osu_updates_test
DB_DATABASE_CHARTS=osu_charts_test

# match with docker-compose.yml
DB_DATABASE=osu_test
ES_INDEX_PREFIX=test_
SCHEMA=test

PAYMENT_SANDBOX=true
5 changes: 3 additions & 2 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ module.exports = {
'plugin:react-hooks/recommended',
'plugin:react/recommended',
],
files: ['resources/js/**/*.{ts,tsx}', 'tests/karma/**/*.ts'],
files: ['resources/js/**/*.{ts,tsx}', 'tests/karma/**/*.{ts,tsx}'],
parser: '@typescript-eslint/parser',
plugins: [
'@typescript-eslint',
Expand Down Expand Up @@ -181,7 +181,7 @@ module.exports = {
browser: false,
node: true,
},
files: ['tests/karma/**/*.ts'],
files: ['tests/karma/**/*.{ts,tsx}'],
parserOptions: {
project: 'tests/karma/tsconfig.json',
sourceType: 'module',
Expand All @@ -198,6 +198,7 @@ module.exports = {
rules: {
'arrow-body-style': 'error',
'arrow-parens': 'error',
'arrow-spacing': 'error',
'brace-style': 'error',
'comma-dangle': ['error', 'always-multiline'],
complexity: 'off',
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ jobs:
- name: Install js dependencies
run: yarn --frozen-lockfile

- run: 'yarn lint --max-warnings 130 > /dev/null'
- run: 'yarn lint --max-warnings 123 > /dev/null'

- run: ./bin/update_licence.sh -nf

Expand Down
35 changes: 35 additions & 0 deletions .github/workflows/pack.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,41 @@ jobs:
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

notify_pending_production_deploy:
if: ${{ github.ref_type == 'tag' }}
runs-on: ubuntu-latest
needs:
- push_to_registry
steps:
-
name: Submit pending deployment notification
run: |
export TITLE="Pending osu-web Production Deployment: $GITHUB_REF_NAME"
export URL="https://github.com/ppy/osu-web/actions/runs/$GITHUB_RUN_ID"
export DESCRIPTION="Docker image was built for tag $GITHUB_REF_NAME and awaiting approval for production deployment:
[View Workflow Run]($URL)"
export ACTOR_ICON="https://avatars.githubusercontent.com/u/$GITHUB_ACTOR_ID"
BODY="$(jq --null-input '{
"embeds": [
{
"title": env.TITLE,
"color": 15098112,
"description": env.DESCRIPTION,
"url": env.URL,
"author": {
"name": env.GITHUB_ACTOR,
"icon_url": env.ACTOR_ICON
}
}
]
}')"
curl \
-H "Content-Type: application/json" \
-d "$BODY" \
"${{ secrets.DISCORD_INFRA_WEBHOOK_URL }}"
push_to_production:
if: ${{ github.ref_type == 'tag' }}
runs-on: ubuntu-latest
Expand Down
8 changes: 8 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,14 @@ jobs:
- name: Run PHPUnit
run: ./bin/phpunit.sh

# TODO: workaround things (beatmaps) being indexed during test above and not cleaned up.
# This used to cause beatmap listing returning cursor with Long.MIN_VALUE for null timetamp
# and errors out when trying to get the next page (es can't parse such value for timestamp)
# but has since been fixed.
# Something should still be done regarding es index between tests though.
- name: Clean indexes
run: php artisan es:index-documents --yes

- name: Run Dusk
run: ./bin/run_dusk.sh

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Please see [CONTRIBUTING.md](CONTRIBUTING.md) for information about the code sta

While we have standards in place, nothing is set in stone. If you have an issue with the way code is structured; with any libraries we are using; with any processes involved with contributing, *please* bring it up. We welcome all feedback so we can make contributing to this project as pain-free as possible.

For those interested, we love to reward quality contributions via [bounties](https://docs.google.com/spreadsheets/d/1jNXfj_S3Pb5PErA-czDdC9DUu4IgUbe1Lt8E7CYUJuE/view?&rm=minimal#gid=523803337), paid out via paypal or osu! supporter tags. Don't hesitate to [request a bounty](https://docs.google.com/forms/d/e/1FAIpQLSet_8iFAgPMG526pBZ2Kic6HSh7XPM3fE8xPcnWNkMzINDdYg/viewform) for your work on this project.
We love to reward quality contributions. If you have made a large contribution or are a regular contributor, you are welcome to [submit an expense via opencollective](https://opencollective.com/ppy/expenses/new). If you have any questions, feel free to [reach out to peppy](mailto:[email protected]) before doing so.

## Seeking Help

Expand Down
3 changes: 2 additions & 1 deletion SETUP.md
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ Note that if you use the bundled docker compose setup, yarn/webpack will be alre
$ php artisan migrate:fresh --seed
```

Run the above command to rebuild the database and seed with sample data. In order for the seeder to seed beatmaps, you must enter a valid osu! API key as the value of the `OSU_API_KEY` property in the `.env` configuration file, as the seeder obtains beatmap data from the osu! API. The key can be obtained at [the "osu! API Access" page](https://old.ppy.sh/p/api), which is currently only available on the old site.
Run the above command to rebuild the database and seed with sample data. In order for the seeder to seed beatmaps, you must enter a valid osu! API key as the value of the `OSU_API_KEY` property in the `.env` configuration file, as the seeder obtains beatmap data from the osu! API. The key can be obtained from [the "Legacy API" section of your account settings page](https://osu.ppy.sh/home/account/edit#legacy-api).

## Continuous asset generation while developing

Expand Down Expand Up @@ -319,6 +319,7 @@ bin/run_dusk.sh
or if using Docker:

```
# `compose exec` doesn't work here due to port conflict with dev instance
docker compose run --rm php test browser
```

Expand Down
9 changes: 8 additions & 1 deletion app/Console/Commands/NotificationsSendMail.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,14 @@ public function handle()
foreach ($userIds->chunk($chunkSize) as $chunk) {
$users = User::whereIn('user_id', $chunk)->get();
foreach ($users as $user) {
dispatch(new UserNotificationDigest($user, $fromId, $toId));
$job = new UserNotificationDigest($user, $fromId, $toId);
try {
$job->handle();
} catch (\Exception $e) {
// catch exception and queue job to be rerun to avoid job exploding and preventing other notifications from being processed.
log_error($e);
dispatch($job);
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion app/Console/Commands/RouteConvert.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ protected function write()
}

if (!$written) {
$this->line(json_encode($this->routeScopesHelper->toArray(), JSON_PRETTY_PRINT));
$this->line(json_encode($this->routeScopesHelper->toArray(), JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
}
}
}
7 changes: 2 additions & 5 deletions app/Events/NewPrivateNotificationEvent.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,14 @@ class NewPrivateNotificationEvent extends NotificationEventBase
{
use SerializesModels;

public $notification;
private $receiverIds;

/**
* Create a new event instance.
*
* @return void
*/
public function __construct(Notification $notification, array $receiverIds)
public function __construct(public Notification $notification, private array $receiverIds)
{
parent::__construct($notification);
parent::__construct();

$this->notification = $notification;
$this->receiverIds = $receiverIds;
Expand Down
17 changes: 17 additions & 0 deletions app/Exceptions/ModelNotSavedException.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,26 @@

namespace App\Exceptions;

use Exception;
use Illuminate\Http\Response;

// This is used for model's saveOrExplode
class ModelNotSavedException extends SilencedException
{
public static function makeResponse(?Exception $e, array $modelFields): Response
{
$json = [
'error' => $e?->getMessage(),
'form_error' => [],
];

foreach ($modelFields as $field => $model) {
$json['form_error'][$field] = $model->validationErrors()->all();
}

return response($json, 422);
}

public function getStatusCode()
{
return 422;
Expand Down
41 changes: 22 additions & 19 deletions app/Http/Controllers/AccountController.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
use App\Models\UserAccountHistory;
use App\Models\UserNotificationOption;
use App\Transformers\CurrentUserTransformer;
use App\Transformers\LegacyApiKeyTransformer;
use App\Transformers\LegacyIrcKeyTransformer;
use Auth;
use DB;
use Mail;
Expand Down Expand Up @@ -111,12 +113,20 @@ public function edit()
$authorizedClients = json_collection(Client::forUser($user), 'OAuth\Client', 'user');
$ownClients = json_collection($user->oauthClients()->where('revoked', false)->get(), 'OAuth\Client', ['redirect', 'secret']);

$legacyApiKey = $user->apiKeys()->available()->first();
$legacyApiKeyJson = $legacyApiKey === null ? null : json_item($legacyApiKey, new LegacyApiKeyTransformer());

$legacyIrcKey = $user->legacyIrcKey;
$legacyIrcKeyJson = $legacyIrcKey === null ? null : json_item($legacyIrcKey, new LegacyIrcKeyTransformer());

$notificationOptions = $user->notificationOptions->keyBy('name');

return ext_view('accounts.edit', compact(
'authorizedClients',
'blocks',
'currentSessionId',
'legacyApiKeyJson',
'legacyIrcKeyJson',
'notificationOptions',
'ownClients',
'sessions'
Expand All @@ -140,7 +150,7 @@ public function update()
try {
$user->fill($params)->saveOrExplode();
} catch (ModelNotSavedException $e) {
return $this->errorResponse($user, $e);
return ModelNotSavedException::makeResponse($e, compact('user'));
}

return json_item($user, new CurrentUserTransformer());
Expand All @@ -153,19 +163,17 @@ public function updateEmail()
$previousEmail = $user->user_email;

if ($user->update($params) === true) {
$addresses = [$user->user_email];
if (present($previousEmail)) {
$addresses[] = $previousEmail;
}
foreach ($addresses as $address) {
Mail::to($address)->locale($user->preferredLocale())->send(new UserEmailUpdated($user));
foreach ([$previousEmail, $user->user_email] as $address) {
if (is_valid_email_format($address)) {
Mail::to($address)->locale($user->preferredLocale())->send(new UserEmailUpdated($user));
}
}

UserAccountHistory::logUserUpdateEmail($user, $previousEmail);

return response([], 204);
} else {
return $this->errorResponse($user);
return ModelNotSavedException::makeResponse(null, compact('user'));
}
}

Expand Down Expand Up @@ -240,7 +248,10 @@ public function updateOptions()
$user->profileCustomization()->fill($profileParams)->saveOrExplode();
}
} catch (ModelNotSavedException $e) {
return $this->errorResponse($user, $e);
return ModelNotSavedException::makeResponse($e, [
'user' => $user,
'user_profile_customization' => $user->profileCustomization(),
]);
}

return json_item($user, new CurrentUserTransformer());
Expand All @@ -252,7 +263,7 @@ public function updatePassword()
$user = Auth::user()->validateCurrentPassword()->validatePasswordConfirmation();

if ($user->update($params) === true) {
if (present($user->user_email)) {
if (is_valid_email_format($user->user_email)) {
Mail::to($user)->send(new UserPasswordUpdated($user));
}

Expand All @@ -262,7 +273,7 @@ public function updatePassword()

return response([], 204);
} else {
return $this->errorResponse($user);
return ModelNotSavedException::makeResponse(null, compact('user'));
}
}

Expand Down Expand Up @@ -291,12 +302,4 @@ public function reissueCode()
{
return UserVerification::fromCurrentRequest()->reissue();
}

private function errorResponse($user, $exception = null)
{
return response([
'form_error' => ['user' => $user->validationErrors()->all()],
'error' => optional($exception)->getMessage(),
], 422);
}
}
9 changes: 5 additions & 4 deletions app/Http/Controllers/ArtistTracksController.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,14 @@ public function index()
$search = new ArtistTrackSearch($params);

$tracks = $search->records();
$data = array_merge([
$index = [
'artist_tracks' => json_collection($tracks, new ArtistTrackTransformer(), ['artist', 'album']),
'search' => ArtistTrackSearchParamsFromRequest::toArray($params),
], cursor_for_response($search->getSortCursor()));
...cursor_for_response($search->getSortCursor()),
];

if (is_json_request()) {
return $data;
return $index;
}

$availableGenres = cache_remember_mutexed(
Expand All @@ -34,7 +35,7 @@ public function index()
fn () => ArtistTrack::distinct()->pluck('genre')->sort()->values(),
);

return ext_view('artist_tracks.index', compact('availableGenres', 'data'));
return ext_view('artist_tracks.index', compact('availableGenres', 'index'));
}

public function show($id)
Expand Down
10 changes: 9 additions & 1 deletion app/Http/Controllers/BeatmapDiscussionsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class BeatmapDiscussionsController extends Controller
{
public function __construct()
{
$this->middleware('auth', ['except' => ['index', 'show']]);
$this->middleware('auth', ['except' => ['index', 'mediaUrl', 'show']]);
$this->middleware('require-scopes:public', ['only' => ['index']]);

parent::__construct();
Expand Down Expand Up @@ -117,6 +117,14 @@ public function index()
return ext_view('beatmap_discussions.index', compact('json', 'search', 'paginator'));
}

public function mediaUrl()
{
$url = get_string(request('url'));

// Tell browser not to request url for a while.
return redirect(proxy_media($url))->header('Cache-Control', 'max-age=600');
}

public function restore($id)
{
$discussion = BeatmapDiscussion::whereNotNull('deleted_at')->findOrFail($id);
Expand Down
Loading

0 comments on commit 5aba3d3

Please sign in to comment.