Skip to content
Merged

3.6.6 #605

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
85103b7
Bump aws/aws-sdk-php from 3.359.13 to 3.368.2 in /backend (#595)
dependabot[bot] Dec 19, 2025
33c62d1
Bump @types/node from 24.3.0 to 24.10.1 in /frontend (#594)
dependabot[bot] Dec 19, 2025
0587ea3
Bump @vueuse/nuxt from 13.6.0 to 14.1.0 in /frontend (#593)
dependabot[bot] Dec 19, 2025
a977c0b
Fix forgot password
Luffyyy Dec 2, 2025
7e5a6df
Add 'plunk' transport configuration to mailers
Luffyyy Dec 2, 2025
1ff0b7f
New Crowdin updates (#586)
Luffyyy Jan 19, 2026
50dadd6
Bump @antfu/utils from 9.2.0 to 9.3.0 in /frontend (#596)
dependabot[bot] Jan 19, 2026
b4b53f7
Bump vue from 3.5.25 to 3.5.26 in /frontend (#597)
dependabot[bot] Jan 19, 2026
7fa456e
Bump typescript-eslint from 8.43.0 to 8.50.0 in /frontend (#598)
dependabot[bot] Jan 19, 2026
d390739
Bump qs from 6.14.0 to 6.14.1 in /frontend (#600)
dependabot[bot] Jan 19, 2026
e97f7a0
Bump devalue from 5.4.2 to 5.6.2 in /frontend (#601)
dependabot[bot] Jan 19, 2026
1aaa485
Bump h3 from 1.15.4 to 1.15.5 in /frontend (#602)
dependabot[bot] Jan 19, 2026
1329048
Bump tar from 7.4.3 to 7.5.3 in /frontend (#603)
dependabot[bot] Jan 19, 2026
142dc4e
Bump phpunit/phpunit from 12.3.11 to 12.5.2 in /backend (#591)
dependabot[bot] Jan 19, 2026
00f2f7d
Bump laravel/telescope from 5.11.3 to 5.15.1 in /backend (#590)
dependabot[bot] Jan 19, 2026
43afa12
Bump axios from 1.12.1 to 1.13.2 in /frontend (#588)
dependabot[bot] Jan 19, 2026
67adb16
Bump fileeye/mimemap from 2.2.2 to 2.2.3 in /backend (#578)
dependabot[bot] Jan 19, 2026
7c694b9
Fix error on registration
Luffyyy Jan 1, 2026
2e75609
Upgrade SEO package to fix an error
Luffyyy Jan 19, 2026
f871f56
Add missing hidden tag ids in models.ts
Luffyyy Jan 19, 2026
3f23ecc
Fix applied global mod managers not showing anything
Luffyyy Jan 19, 2026
190ecf7
Fix empty names
Luffyyy Jan 19, 2026
dec3714
Fix not being able to delete users sometimes
Luffyyy Jan 19, 2026
ee88cca
Remove logging for null value check in validation
Luffyyy Jan 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions backend/app/Http/Controllers/FileController.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public function beginUpload(Request $request, Mod $mod) {
$remainingStorage = $mod->currentStorage;

$val = $request->validate([
'name' => 'string|min:1|max:100',
'name' => 'string|min_strict:1|max:100',
'size' => "required|int|max:{$remainingStorage}"
]);

Expand All @@ -76,7 +76,7 @@ public function fileBeginUpload(Request $request, File $file) {
$remainingStorage = $file->mod->currentStorage - $file->size;

$val = $request->validate([
'name' => 'string|min:1|max:100',
'name' => 'string|min_strict:1|max:100',
'size' => "required|int|max:{$remainingStorage}"
]);

Expand Down Expand Up @@ -241,7 +241,7 @@ public function update(Request $request, File $file)
$remainingStorage = $file->mod->currentStorage - $file->size;

$val = $request->validate([
'name' => 'string|min:1|max:100',
'name' => 'string|min_strict:1|max:100',
'label' => 'string|nullable|max:100',
'desc' => 'string|nullable|max:1000',
'version' => 'string|nullable|max:255',
Expand Down
2 changes: 1 addition & 1 deletion backend/app/Http/Controllers/GameController.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public function __construct() {
public function update(Request $request, Game $game=null)
{
$validateArr = [
'name' => 'string|max:150',
'name' => 'string|min_strict:3|max:150',
'buttons' => 'nullable|string|max:1000',
'thumbnail_file' => 'nullable|max:512000|mimes:png,webp,avif,gif,jpg',
'banner_file' => 'nullable|max:512000|mimes:png,webp,avif,gif,jpg',
Expand Down
4 changes: 2 additions & 2 deletions backend/app/Http/Controllers/InstructsTemplateController.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public function __construct() {
}
/**
* List instructions templates
*
*
* @authenticated
*/
public function index(Game $game, FilteredRequest $request)
Expand Down Expand Up @@ -56,7 +56,7 @@ public function show(Game $game, InstructsTemplate $instructsTemplate)
public function update(Request $request, Game $game, InstructsTemplate $instructsTemplate=null)
{
$val = $request->validate([
'name' => 'string|max:150',
'name' => 'string|min_strict:3|max:150',
'instructions' => 'string|nullable|max:30000',
'localized' => 'boolean|nullable',
]);
Expand Down
4 changes: 2 additions & 2 deletions backend/app/Http/Controllers/LinkController.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public function show(Link $link)
public function update(Request $request, Mod $mod, Link $link=null)
{
$val = $request->validate([
'name' => 'required|min:3|max:255',
'name' => 'required|min_strict:3|max:255',
'url' => 'required|url|min:3|max:1000',
'desc' => 'string|nullable|max:1000',
'label' => 'string|nullable|max:100',
Expand Down Expand Up @@ -103,7 +103,7 @@ public function registerDownload(Request $request, Link $link)
{
ModService::registerDownload($link);
}

/**
* Delete a link
*
Expand Down
6 changes: 3 additions & 3 deletions backend/app/Http/Controllers/LoginController.php
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public function logout(Request $request) {
public function register(Request $request)
{
$val = $request->validate([
'name' => ['required'],
'name' => 'required|string|min_strict:3|max:30',
'unique_name' => ['alpha_dash:ascii', 'not_regex:/^\d+$/', 'nullable', 'min:3', 'max:50'],
'email' => ['required', 'email', new \nickurt\StopForumSpam\Rules\IsSpamEmail(2)],
'password' => ['required', APIService::getPasswordRule(), 'max:128'],
Expand Down Expand Up @@ -240,7 +240,7 @@ public function socialiteLogin(Request $request, string $provider)
$found = false;
while(!$found) {
$current = $uniqueName.$num;
if (!Arr::first($users, fn($val) => Str::lower($val->unique_name) === $current)) {
if (!Arr::first($users->toArray(), fn($val) => Str::lower($val->unique_name) === $current)) {
$uniqueName = $current;
$found = true;
} else {
Expand Down Expand Up @@ -291,7 +291,7 @@ public function validateProvider(string $provider)
public function forgotPassword(Request $request)
{
$val = $request->validate(['email' => 'required|email|max:255']);
$email = [Str::lower($val['email'])];
$email = ['email' => Str::lower($val['email'])];
Password::sendResetLink($email);
# Is there a need to handle errors?
}
Expand Down
4 changes: 2 additions & 2 deletions backend/app/Http/Controllers/ModManagerController.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public function index(FilteredRequest $request, Game $game=null)
$user = Auth::user();
if (isset($game)) {
$query->where('game_id', $game->id);
}
}
if (isset($val['global']) && $val['global']) {
$query->orWhereNull('game_id');
}
Expand Down Expand Up @@ -70,7 +70,7 @@ public function show(ModManager $modManager)
public function update(Request $request, ModManager $modManager = null, Game $game=null)
{
$val = $request->validate([
'name' => 'string|min:3|max:100',
'name' => 'string|min_strict:3|max:100',
'download_url' => 'string|max:1000',
'site_url' => 'url|nullable|max:1000',
'game_id' => 'integer|min:1|nullable|exists:games,id',
Expand Down
4 changes: 2 additions & 2 deletions backend/app/Http/Controllers/TagController.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,9 @@ public function show(Tag $tag)
public function update(Request $request, Game $game=null, Tag $tag=null)
{
$val = $request->validate([
'name' => 'string|required|min:2|max:100',
'name' => 'string|required|min_strict:2|max:100',
'color' => 'string|required|hex_color|max:8',
'notice' => 'string|nullable|min:3|max:1000',
'notice' => 'string|nullable|min_strict:3|max:1000',
'notice_type' => 'string|nullable|in:info,warning,danger',
'type' => 'string|nullable|in:all,forum,mod',
'notice_localized' => 'boolean|nullable',
Expand Down
8 changes: 4 additions & 4 deletions backend/app/Http/Controllers/ThreadController.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ public function uploadThumbnail(Request $request, Thread $thread) {
public function store(Request $request, Forum $forum)
{
$val = $request->validate([
'name' => 'string|min:3|max:150',
'content' => 'string|spam_check|required|min:2|max:30000',
'name' => 'string|min_strict:3|max:150',
'content' => 'string|spam_check|required|min_strictn:2|max:30000',
'announce_until' => 'date|nullable',
'announce' => 'boolean',
'tag_ids' => 'array|nullable',
Expand Down Expand Up @@ -142,8 +142,8 @@ public function show(Thread $thread)
public function update(Request $request, Thread $thread)
{
$val = $request->validate([
'name' => 'string|min:3|max:150',
'content' => 'string|spam_check|min:2|max:30000',
'name' => 'string|min_strict:3|max:150',
'content' => 'string|spam_check|min_strict:2|max:30000',
'category_id' => 'integer|min:1|nullable|exists:forum_categories,id',
'forum_id' => 'integer|min:1|nullable|exists:forums,id',
'answer_comment_id' => 'integer|min:1|nullable|exists:comments,id',
Expand Down
6 changes: 5 additions & 1 deletion backend/app/Http/Controllers/UserController.php
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ public function update(Request $request, User $user)
];

$valRules =[
'name' => 'string|nullable|min:3|max:30',
'name' => 'string|nullable|min_strict:3|max:30',
'unique_name' => ['alpha_dash:ascii', 'not_regex:/^\d+$/', 'nullable', 'min:3', 'max:50'],
'avatar_file' => ['nullable', 'is_image'],
'custom_color' => 'string|max:7|nullable',
Expand Down Expand Up @@ -211,6 +211,10 @@ public function update(Request $request, User $user)

$val = $request->validate($valRules);

APIService::normalizeStrings($val, 'name');

APIService::nullToUndefined($val, 'name', 'unique_name', 'email');

APIService::nullToEmptyStr($val,
'custom_color',
'bio',
Expand Down
4 changes: 2 additions & 2 deletions backend/app/Http/Requests/ModUpsertRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ public function authorize()
public function rules()
{
return [
'name' => 'string|min:3|max:100',
'desc' => 'string|min:3|max:30000',
'name' => 'string|min_strict:3|max:100',
'desc' => 'string|min_strict:3|max:30000',
'license' => 'string|spam_check|nullable|max:30000',
'changelog' => 'string|spam_check|nullable|max:30000',
'instructions' => 'string|spam_check|nullable|max:30000',
Expand Down
4 changes: 2 additions & 2 deletions backend/app/Http/Requests/UpsertRoleRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ public function authorize()
public function rules()
{
return [
'name' => 'string|nullable|min:2|max:30',
'tag' => 'string|nullable|min:2|max:30',
'name' => 'string|nullable|min_strict:2|max:30',
'tag' => 'string|nullable|min_strict:2|max:30',
'desc' => 'string|nullable|max:1000',
'color' => 'string|nullable|max:8',
'is_vanity' => 'boolean',
Expand Down
14 changes: 14 additions & 0 deletions backend/app/Providers/AppServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,20 @@ public function boot()
Relation::macro('_constraints', fn() => self::$constraints);
Relation::macro('_setConstraints', fn($val) => self::$constraints = $val);

Validator::extendImplicit('min_strict', function ($attribute, $value, $parameters, ValidationValidator $validator) {
// Only allow null values when nullable rule is used
if (is_null($value)) {
return $validator->hasRule($attribute, 'Nullable');
}

$clean = APIService::normalizeString($value);
return mb_strlen($clean) >= (int)$parameters[0];
}, 'The :attribute must be at least :min characters.');

Validator::replacer('min_strict', function ($message, $attribute, $rule, $parameters) {
return str_replace(':min', $parameters[0], $message);
});

Validator::extend('email_or_url', function ($attribute, $value, $parameters, ValidationValidator $validator) {
if (!$validator->validateEmail($attribute, $value, ['rfc']) && !$validator->validateUrl($attribute, $value)) {
return false;
Expand Down
40 changes: 40 additions & 0 deletions backend/app/Services/APIService.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,24 @@ public static function appendToItems(Paginator $paginator, string $key)
}
}

/**
* Handles null values by removing them entirely from the array
* Useful for cases where you KNOW that the value cannot be null and null is as good as undefined
*
* @param array $arr
* @param string $key
* @return void
*/
public static function nullToUndefined(array &$arr, string ...$keys)
{
foreach ($keys as $key) {
if (array_key_exists($key, $arr) && is_null($arr[$key])) {
unset($arr[$key]);
}
}
}


/**
* The opposite of ConvertEmptyStringsToNull, this converst nulls we expect to be empty at times.
* For example strings, if you send them as empty string, PHP doesn't know if it's null or empty string.
Expand Down Expand Up @@ -99,6 +117,28 @@ public static function nullToEmptyArr(array &$arr, string ...$keys)
}
}

/**
* Removes empty unicode strings, this is useful for strings which you want to ensure are not empty
*
* @param string $str
* @return void
*/
public static function normalizeString(string $str) {
// Remove ALL invisible / control characters
$str = preg_replace('/[\p{C}]/u', '', $str);

// Normalize whitespace
return trim(preg_replace('/\s+/u', ' ', $str));
}

public static function normalizeStrings(array &$arr, string ...$keys) {
foreach ($keys as $key) {
if (array_key_exists($key, $arr) && is_string($arr[$key])) {
$arr[$key] = self::normalizeString($arr[$key]);
}
}
}

/**
* Stores an UploadedFile $file into r2 storage
*
Expand Down
2 changes: 1 addition & 1 deletion backend/app/Services/CommentService.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public static function index(FilteredRequest $request, Model $commentable, array
public static function store(Request $request, Model $commentable, array $extraSet=null)
{
$val = $request->validate([
'content' => 'string|required|min:2|max:5000',
'content' => 'string|required|min_strict:2|max:5000',
'mentions' => 'array',
'mentions.*' => 'string',
'reply_to' => 'integer|nullable|min:1|exists:comments,id,reply_to,NULL'
Expand Down
10 changes: 5 additions & 5 deletions backend/app/Services/DependencyService.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public static function store(Request $request, $dependable)
if (!isset($dependency)) {
abort(409, 'already exists');
}

$dependency->loadMissing('mod');

return $dependency;
Expand All @@ -46,8 +46,8 @@ public static function update(Request $request, $dependable, Dependency $depende
$val = null;
if ($dependency->offsite) {
$val = $request->validate([
'name' => 'string|min:3|max:150',
'url' => 'url|min:3|max:1000',
'name' => 'string|min_strict:3|max:150',
'url' => 'url|min:3|max:1000',
'optional' => 'boolean',
'order' => 'integer'
]);
Expand All @@ -61,7 +61,7 @@ public static function update(Request $request, $dependable, Dependency $depende

$dependency->update($val);
$dependency->load('mod');

return $dependency;
}

Expand All @@ -72,4 +72,4 @@ public static function destroy(Request $request, $dependable, Dependency $depend
{
$dependency->delete();
}
}
}
Loading