Skip to content

Commit

Permalink
Merge branch 'master' into smiley-replacer
Browse files Browse the repository at this point in the history
  • Loading branch information
notbakaneko authored Nov 30, 2023
2 parents 35acaff + 8c390d8 commit 985d7cc
Show file tree
Hide file tree
Showing 17 changed files with 238 additions and 142 deletions.
2 changes: 1 addition & 1 deletion app/Http/Controllers/AccountController.php
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ public function verify()

public function verifyLink()
{
$state = UserVerificationState::fromVerifyLink(request('key'));
$state = UserVerificationState::fromVerifyLink(get_string(request('key')) ?? '');

if ($state === null) {
UserVerification::logAttempt('link', 'fail', 'incorrect_key');
Expand Down
39 changes: 39 additions & 0 deletions app/Libraries/SignedRandomString.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

// Copyright (c) ppy Pty Ltd <[email protected]>. Licensed under the GNU Affero General Public License v3.0.
// See the LICENCE file in the repository root for full licence text.

declare(strict_types=1);

namespace App\Libraries;

class SignedRandomString
{
public static function create(int $randomSize): string
{
$key = random_bytes($randomSize);
$hmac = static::hmac($key);

return base64url_encode($hmac.$key);
}

public static function isValid(string $input): bool
{
$bin = base64url_decode($input);
if ($bin === null) {
return false;
}

// hmac size for sha1 is 20
$hmac = substr($bin, 0, 20);
$key = substr($bin, 20);
$expectedHmac = static::hmac($key);

return hash_equals($expectedHmac, $hmac);
}

private static function hmac(string $key): string
{
return hash_hmac('sha1', $key, \Crypt::getKey(), true);
}
}
6 changes: 5 additions & 1 deletion app/Libraries/UserVerificationState.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ public static function fromCurrentRequest()

public static function fromVerifyLink($linkKey)
{
if (!SignedRandomString::isValid($linkKey)) {
return null;
}

$params = cache()->get("verification:{$linkKey}");

if ($params !== null) {
Expand Down Expand Up @@ -76,7 +80,7 @@ public function issue()

// 1 byte = 2^8 bits = 16^2 bits = 2 hex characters
$key = bin2hex(random_bytes(config('osu.user.verification_key_length_hex') / 2));
$linkKey = bin2hex(random_bytes(32));
$linkKey = SignedRandomString::create(32);
$expires = now()->addHours(5);

$this->session->put('verification_key', $key);
Expand Down
3 changes: 2 additions & 1 deletion app/Providers/AuthServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use Carbon\Carbon;
use Illuminate\Contracts\Auth\StatefulGuard;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Laravel\Passport\Http\Controllers\AccessTokenController;
use Laravel\Passport\Http\Controllers\ApproveAuthorizationController;
use Laravel\Passport\Http\Controllers\DenyAuthorizationController;
use Laravel\Passport\Passport;
Expand Down Expand Up @@ -52,7 +53,7 @@ public function boot()
// RouteServiceProvider current runs before our provider, so Passport's default routes will override
// those set in routes/web.php.
Route::group(['prefix' => 'oauth', 'as' => 'oauth.'], function () {
Route::post('token', '\Laravel\Passport\Http\Controllers\AccessTokenController@issueToken')->middleware('throttle')->name('passport.token');
Route::post('token', AccessTokenController::class.'@issueToken')->middleware('throttle')->name('passport.token');
Route::get('authorize', AuthorizationController::class.'@authorize')
->middleware(['web', 'verify-user'])
->name('authorizations.authorize');
Expand Down
22 changes: 15 additions & 7 deletions app/helpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,18 @@ function background_image($url, $proxy = true)
return sprintf(' style="background-image:url(\'%s\');" ', e($url));
}

function base64url_decode(string $value): ?string
{
return null_if_false(base64_decode(strtr($value, '-_', '+/'), true));
}

function base64url_encode(string $value): string
{
// url safe base64
// reference: https://datatracker.ietf.org/doc/html/rfc4648#section-5
return rtrim(strtr(base64_encode($value), '+/', '-_'), '=');
}

function beatmap_timestamp_format($ms)
{
$s = $ms / 1000;
Expand Down Expand Up @@ -310,13 +322,9 @@ function cursor_decode($cursorString): ?array

function cursor_encode(?array $cursor): ?string
{
if ($cursor === null) {
return null;
}

// url safe base64
// reference: https://datatracker.ietf.org/doc/html/rfc4648#section-5
return rtrim(strtr(base64_encode(json_encode($cursor)), '+/', '-_'), '=');
return $cursor === null
? null
: base64url_encode(json_encode($cursor));
}

function cursor_for_response(?array $cursor): array
Expand Down
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
}
],
"require": {
"ext-ds": "*",
"ext-redis": "*",
"anhskohbo/no-captcha": "^3.2",
"chaseconey/laravel-datadog-helper": ">=1.2.0",
"egulias/email-validator": "*",
Expand All @@ -40,7 +42,6 @@
"maennchen/zipstream-php": "^2.1",
"mariuzzo/laravel-js-localization": "*",
"paypal/paypal-checkout-sdk": "*",
"php-ds/php-ds": "^1.3",
"sentry/sentry-laravel": "*",
"symfony/yaml": "*",
"tightenco/ziggy": ">=0.8.1",
Expand Down
74 changes: 11 additions & 63 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

70 changes: 14 additions & 56 deletions config/app.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php

use Illuminate\Support\Facades\Facade;
use Illuminate\Support\ServiceProvider;

return [

Expand Down Expand Up @@ -175,67 +176,24 @@
|
*/

'providers' => [

/*
* Laravel Framework Service Providers...
*/
Illuminate\Auth\AuthServiceProvider::class,
Illuminate\Broadcasting\BroadcastServiceProvider::class,
Illuminate\Bus\BusServiceProvider::class,
Illuminate\Cache\CacheServiceProvider::class,
Illuminate\Foundation\Providers\ConsoleSupportServiceProvider::class,
// Illuminate\Cookie\CookieServiceProvider::class,
Illuminate\Database\DatabaseServiceProvider::class,
Illuminate\Encryption\EncryptionServiceProvider::class,
Illuminate\Filesystem\FilesystemServiceProvider::class,
Illuminate\Foundation\Providers\FoundationServiceProvider::class,
// Illuminate\Hashing\HashServiceProvider::class,
Illuminate\Mail\MailServiceProvider::class,
Illuminate\Notifications\NotificationServiceProvider::class,
Illuminate\Pagination\PaginationServiceProvider::class,
Illuminate\Pipeline\PipelineServiceProvider::class,
Illuminate\Queue\QueueServiceProvider::class,
Illuminate\Redis\RedisServiceProvider::class,
Illuminate\Auth\Passwords\PasswordResetServiceProvider::class,
// We're using our own SessionServiceProvider so we can override the session id naming (for redis key namespacing)
App\Providers\SessionServiceProvider::class,
Illuminate\Translation\TranslationServiceProvider::class,
Illuminate\Validation\ValidationServiceProvider::class,
Illuminate\View\ViewServiceProvider::class,

/*
* Package Service Providers...
*/
GrahamCampbell\GitHub\GitHubServiceProvider::class,
Mariuzzo\LaravelJsLocalization\LaravelJsLocalizationServiceProvider::class,
Laravel\Tinker\TinkerServiceProvider::class,

/*
* Application Service Providers...
*/
'providers' => ServiceProvider::defaultProviders()->except([
Illuminate\Cookie\CookieServiceProvider::class,
Illuminate\Hashing\HashServiceProvider::class,
Illuminate\Session\SessionServiceProvider::class,
])->merge([
App\Providers\AppServiceProvider::class,
App\Providers\AuthServiceProvider::class,
App\Providers\EventServiceProvider::class,
// Override default migrate:fresh
App\Providers\MigrationServiceProvider::class,
App\Providers\RouteServiceProvider::class,

/*
* After DB transaction commit support
*/
// Override the session id naming (for redis key namespacing)
App\Providers\SessionServiceProvider::class,
// After DB transaction commit support
App\Providers\TransactionStateServiceProvider::class,

/*
* OAuth2 Setup
*/

App\Providers\AuthServiceProvider::class,
Laravel\Passport\PassportServiceProvider::class,

/* Datadog Metrics */
ChaseConey\LaravelDatadogHelper\LaravelDatadogHelperServiceProvider::class,

/* Override default migrate:fresh */
App\Providers\MigrationServiceProvider::class,
],
Mariuzzo\LaravelJsLocalization\LaravelJsLocalizationServiceProvider::class,
])->toArray(),

/*
|--------------------------------------------------------------------------
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

// Copyright (c) ppy Pty Ltd <[email protected]>. Licensed under the GNU Affero General Public License v3.0.
// See the LICENCE file in the repository root for full licence text.

declare(strict_types=1);

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
public function up(): void
{
Schema::table('multiplayer_scores_high', function (Blueprint $table) {
$table->unsignedInteger('attempts')->default(0)->change();
});
}

public function down(): void
{
Schema::table('multiplayer_scores_high', function (Blueprint $table) {
$table->unsignedTinyInteger('attempts')->default(0)->change();
});
}
};
8 changes: 7 additions & 1 deletion resources/css/bem/chat-conversation-panel.less
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,15 @@
display: flex;
flex-direction: column;
flex: 1;
overflow-y: auto; // without this, firefox scroll breaks
position: relative;

@media @mobile {
overflow-y: hidden; // Needed to limit the height of the panel so chat-conversation is scrollable and
// chat-conversation-list doesn't become 0 height on mobile.
// height: 100% alone doesn't work.
// The panel itself should not be scrollable.
}

&__instructions {
margin-top: 10px;
}
Expand Down
Loading

0 comments on commit 985d7cc

Please sign in to comment.