Skip to content
Merged

3.6.7 #639

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
92 commits
Select commit Hold shift + click to select a range
5717432
Make mod manager buttons more user friendly
Luffyyy Jan 24, 2026
aa66228
Merge branch 'prod'
Luffyyy Feb 2, 2026
b88718b
New translations en.json (French)
Luffyyy Jan 25, 2026
8e0bbc4
New translations en.json (Spanish)
Luffyyy Jan 25, 2026
a823d6b
New translations en.json (Czech)
Luffyyy Jan 25, 2026
81014f3
New translations en.json (German)
Luffyyy Jan 25, 2026
9b3e301
New translations en.json (Hungarian)
Luffyyy Jan 25, 2026
ed53140
New translations en.json (Italian)
Luffyyy Jan 25, 2026
901ab72
New translations en.json (Japanese)
Luffyyy Jan 25, 2026
811b711
New translations en.json (Korean)
Luffyyy Jan 25, 2026
26d21ca
New translations en.json (Polish)
Luffyyy Jan 25, 2026
77cefe5
New translations en.json (Russian)
Luffyyy Jan 25, 2026
0fa2b93
New translations en.json (Turkish)
Luffyyy Jan 25, 2026
b532ac5
New translations en.json (Chinese Simplified)
Luffyyy Jan 25, 2026
0d824c5
New translations en.json (Portuguese, Brazilian)
Luffyyy Jan 25, 2026
215dd27
New translations en.json (Indonesian)
Luffyyy Jan 25, 2026
0b05cb9
New translations en.json (Czech)
Luffyyy Jan 27, 2026
b99899f
New translations en.json (Czech)
Luffyyy Jan 27, 2026
47c4681
New translations en.json (Spanish)
Luffyyy Jan 29, 2026
2fad689
Search games and show game on searched mods
Luffyyy Feb 2, 2026
fee13a6
Fix not being able to upload files when not enough storage is left
Luffyyy Jan 28, 2026
f8c1ff9
Fix edit mod uploader not taking allowed storage into account
Luffyyy Jan 28, 2026
c4375ec
Fix game admins not being able to create a mod manager
Luffyyy Jan 29, 2026
d69f449
Allow game admins to increase their storage
Luffyyy Jan 29, 2026
81f2573
Ensure email is lower case
Luffyyy Jan 30, 2026
0ad6de9
Fix not being able to replace a file properly
Luffyyy Jan 31, 2026
62bb334
Fix permission check on game role
Luffyyy Jan 31, 2026
71cc013
Search games and show game on searched mods
Luffyyy Feb 2, 2026
54b92e0
Merge branch 'main' of https://github.com/ModWorkshop/frontend
Luffyyy Feb 2, 2026
dbab340
Add Tebex and validation webhook
Luffyyy Feb 3, 2026
6ff24c3
Move Tebex webhook away from auth
Luffyyy Feb 3, 2026
65b34d2
Fix Tebex webhook not using POST
Luffyyy Feb 3, 2026
cd50662
Fix Tebex not being able to access PHP's input due to Laravel
Luffyyy Feb 4, 2026
92b7910
Fix Tebex webhook IP verification
Luffyyy Feb 4, 2026
ee0f286
Fun
Luffyyy Feb 4, 2026
e27f5f8
PHP is fun
Luffyyy Feb 4, 2026
cdd4097
Test
Luffyyy Feb 4, 2026
f6a3d21
Debugging tebex thing
Luffyyy Feb 4, 2026
db12398
Use a fork version for Tebex SDK
Luffyyy Feb 13, 2026
068ff63
fix: cursor-move icon component name
KashEight Feb 15, 2026
3b6d813
Merge branch 'prod'
Luffyyy Feb 20, 2026
049f195
Test Tebex package
Luffyyy Feb 22, 2026
7bb7574
More Tebex supporter stuff
Luffyyy Mar 2, 2026
0963814
Fix missing provider ID when making supporter sub
Luffyyy Mar 2, 2026
2f79cce
Bump genealabs/laravel-model-caching from 12.0.4 to 13.0.0 in /backend
dependabot[bot] Mar 2, 2026
42dba17
Bump rollup from 4.55.2 to 4.59.0 in /frontend
dependabot[bot] Feb 28, 2026
6457e80
Bump koa from 2.16.3 to 2.16.4 in /frontend
dependabot[bot] Feb 28, 2026
4098aea
Bump tar from 7.5.3 to 7.5.9 in /frontend
dependabot[bot] Feb 19, 2026
f136cf7
Bump @isaacs/brace-expansion from 5.0.0 to 5.0.1 in /frontend
dependabot[bot] Feb 3, 2026
982f70f
Bump lodash from 4.17.21 to 4.17.23 in /frontend
dependabot[bot] Jan 22, 2026
b2bc39a
Bump markdown-it from 14.1.0 to 14.1.1 in /frontend
dependabot[bot] Feb 13, 2026
eef7feb
Bump qs from 6.14.1 to 6.14.2 in /frontend
dependabot[bot] Mar 2, 2026
85b5c44
Bump axios from 1.13.2 to 1.13.5 in /frontend
dependabot[bot] Feb 11, 2026
6255423
Bump jcupitt/vips from 2.5.0 to 2.6.1 in /backend
dependabot[bot] Mar 2, 2026
15fd98d
Bump devalue from 5.6.2 to 5.6.3 in /frontend
dependabot[bot] Feb 20, 2026
d0217c2
Bump @pinia/nuxt from 0.11.2 to 0.11.3 in /frontend
dependabot[bot] Jan 26, 2026
abe8f11
Bump @vueuse/core from 13.9.0 to 14.1.0 in /frontend
dependabot[bot] Jan 26, 2026
d6ba090
Bump @nuxt/devtools from 2.7.0 to 3.1.1 in /frontend
dependabot[bot] Mar 2, 2026
07e7e30
Bump laravel/telescope from 5.17.0 to 5.18.0 in /backend
dependabot[bot] Mar 2, 2026
80456ca
Update source file en.json
Luffyyy Feb 2, 2026
56e5a9d
Remove Tebex
Luffyyy Mar 3, 2026
a3ebc9f
Remove Nitro supporter stuff
Luffyyy Mar 3, 2026
cf26431
Fix error in threads
Luffyyy Mar 3, 2026
66c065a
Force update Nuxt
Luffyyy Mar 3, 2026
f5f9238
Move to donations only for now
Luffyyy Mar 3, 2026
0c1c1e6
Remove useWatchedFetchMany and use useFetchMany
Luffyyy Mar 4, 2026
5de5c5c
New Crowdin updates (#637)
Luffyyy Mar 4, 2026
6e0af9e
Allow moderators to comment despite being blocked
Luffyyy Mar 4, 2026
8e1037f
Merge branch 'main' of https://github.com/ModWorkshop/frontend
Luffyyy Mar 4, 2026
ae22f73
Improve search box
Luffyyy Mar 5, 2026
e73f32e
Fix mod list instantly searching on typing
Luffyyy Mar 5, 2026
d830446
Fix an error in mod-banner
Luffyyy Mar 5, 2026
7f9cedf
Some migration changes for supporter
Luffyyy Mar 5, 2026
5c888a0
Fix nothing found showing in the new search menu when loading
Luffyyy Mar 5, 2026
d19d0cd
Add created_at timestamp to views and downloads tables
Luffyyy Mar 6, 2026
17de093
Update Frankenphp to latest
Luffyyy Mar 6, 2026
7c1f5e4
Create timestamp for ModView, ModDownload and DownloadableDownload
Luffyyy Mar 6, 2026
438ee2d
Fix an error in mod-list
Luffyyy Mar 6, 2026
9c85c19
Fix issue with m-select and useRouteQuery
Luffyyy Mar 6, 2026
1737ab1
Adjust inputs and select design a little
Luffyyy Mar 6, 2026
c689e33
Improve search-list-mod
Luffyyy Mar 6, 2026
368bc4a
Show only 1 tag at a time in the mod filters select
Luffyyy Mar 6, 2026
afdb125
Line clamp on sarch-list-mod
Luffyyy Mar 6, 2026
bb3c2e5
Bump svgo from 4.0.0 to 4.0.1 in /frontend (#640)
dependabot[bot] Mar 6, 2026
d6bbc3f
Bump tar from 7.5.9 to 7.5.10 in /frontend (#641)
dependabot[bot] Mar 6, 2026
7e318dc
New Crowdin updates (#638)
Luffyyy Mar 6, 2026
ea4bb3c
Bump dompurify from 3.3.1 to 3.3.2 in /frontend (#642)
dependabot[bot] Mar 6, 2026
dbf0c2a
Return a reactive object in useFetchMany
Luffyyy Mar 6, 2026
28dceb6
Merge branch 'main' of https://github.com/ModWorkshop/frontend
Luffyyy Mar 6, 2026
908e831
Add loading state to games page
Luffyyy Mar 6, 2026
83f5910
Revert checkbox gap to 1
Luffyyy Mar 6, 2026
681aa0c
Adjust select height again
Luffyyy Mar 6, 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
2 changes: 1 addition & 1 deletion backend/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#syntax=docker/dockerfile:1
FROM dunglas/frankenphp:1.8.0-php8.3-bookworm AS build
FROM dunglas/frankenphp:1.11.3-php8.3-bookworm AS build

RUN apt-get update && apt-get install -y --no-install-recommends supervisor

Expand Down
2 changes: 0 additions & 2 deletions backend/app/Console/Kernel.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
use App\Jobs\CalculateModCounts;
use App\Jobs\CalculatePopularity;
use App\Jobs\CalculateThreadComments;
use App\Jobs\CheckUsersSubscriptionStatus;
use App\Jobs\DeleteLoosePendingFiles;
use App\Jobs\DeleteOldAuditLogs;
use App\Jobs\DeleteUnverifiedUsers;
Expand Down Expand Up @@ -39,7 +38,6 @@ protected function schedule(Schedule $schedule)
$schedule->job(new DeleteOldAuditLogs)->everySixHours();
$schedule->job(new CalculateThreadComments)->everyTwoHours();
$schedule->job(new RemoveExpiredRequests)->everyTwoHours();
$schedule->job(new CheckUsersSubscriptionStatus)->everyThirtyMinutes();
$schedule->job(new DeleteLoosePendingFiles)->everyThreeMinutes();

$schedule->command('sitemap:generate')->everyTwoHours();
Expand Down
5 changes: 4 additions & 1 deletion backend/app/Http/Controllers/ModController.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
use App\Services\Utils;
use Arr;
use Auth;
use Carbon\Carbon;
use DB;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Http\Request;
Expand Down Expand Up @@ -369,7 +370,9 @@ public function registerView(Request $request, Mod $mod)
return;
}

$view = new ModView();
$view = new ModView([
'created_at' => Carbon::now()
]);
$view->mod_id = $mod->id;
if (isset($user)) {
$view->user_id = $user->id;
Expand Down
138 changes: 126 additions & 12 deletions backend/app/Http/Controllers/SupporterController.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,16 @@
use Carbon\Carbon;
use Illuminate\Http\Request;
use App\Http\Resources\BaseResource;
use App\Models\Subscription;
use App\Models\SupporterPackage;
use App\Models\SupporterSubscription;
use App\Models\SupporterTransaction;
use App\Models\User;
use App\Services\APIService;
use Illuminate\Http\Response;

const PAYMENT_STATUS = [
1 => 'complete',
2 => 'refunded'
];
/**
* @group Supporters
*/
Expand Down Expand Up @@ -103,14 +109,122 @@ public function destroy(Supporter $supporter)
$supporter->delete();
}

/**
* Checks nitro to update the subscription data
*
* @authenticated
*
* @hideFromApiDocumentation
*/
public function nitroCheck() {
return APIService::nitroCheck($this->user());
}
// public function getTebexProject() {
// return Headless::setProject(env('TEBEX_PUBLIC_KEY'));
// }

// public function createTebexBasketWithPackage(Request $request) {
// $val = $request->validate([
// 'supporter_package_id' => "int|required|exists:supporter_packages,id"
// ]);

// Checkout::setApiKeys(env('TEBEX_PROJECT_ID'), env('TEBEX_PRIVATE_KEY'));

// $userId = $this->userId();
// $package = SupporterPackage::find($val['supporter_package_id']);

// $project = $this->getTebexProject();
// $basket = $project->createBasket(env('TEBEX_RETURN_URL'), env('TEBEX_RETURN_URL'));

// $basket->addPackage($project->getPackage($package->package_id));
// $basket = $basket->getBasket();
// $ident = $basket->getIdent();

// SupporterSubscription::create([ // Save the basket in the DB so we know who initiated this basket and who to give it to when webhook sends purchase complete
// 'user_id' => $userId,
// 'supporter_package_id' => $package->id,
// 'price' => $package->price,
// 'status' => 'waiting',
// 'provider' => 'tebex',
// 'provider_id' => 'tbx-r-'.$basket->getId()
// ]);

// return ['ident' => $ident];
// }

// public function tebexWebhook() {
// // Issue: Tebex uses REMOTE_ADDR to ensure the IP is not tempered with
// // This however isn't an issue on our end as we use a Proxy and replace that header with Caddy
// if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
// $_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_X_FORWARDED_FOR'];
// }

// Webhooks::setSecretKey(env('TEBEX_WEBHOOK_SECRET_KEY'));

// $json = file_get_contents('php://input');
// $webhook = Webhook::parse($json);

// // Respond to validation endpoint
// if ($webhook->isType(\Tebex\Webhook\VALIDATION_WEBHOOK)) {
// return ["id" => $webhook->getId()];
// } else if ($webhook->isTypeOfPayment()) {
// /**
// * @var PaymentSubject
// */
// $subject = $webhook->getSubject();
// $prod = $subject->getProducts()[0];
// $ref = $subject->getRecurringPaymentReference();
// $sub = SupporterSubscription::find($ref);

// assert(isset($sub), "Reference {$ref} does not exist on site. Fix manually.");

// $user = User::find($sub->user_id);
// $expiryDate = Carbon::parse($prod->getExpiresAt());

// $transId = $subject->getTransactionId();
// $trans = SupporterTransaction::where('provider', 'tebex')->where('provider_id', $transId);
// if (!isset($trans)) {
// $trans = SupporterTransaction::create([
// 'user_id' => $user->id,
// 'supporter_package_id' => $sub->supporter_package_id,
// 'supporter_subcription_id' => $sub->id,
// 'price' => $sub->price,
// 'status' => 'complete',
// 'provider' => 'tebex',
// 'provider_id' => $subject->getTransactionId()
// ]);
// }
// $trans->update([
// 'status' => PAYMENT_STATUS[$subject->getStatus()] ?? 'failed'
// ]);

// switch ($webhook->getType()) {
// case PAYMENT_COMPLETED:
// Supporter::create([
// 'supporter_transaction_id' => $trans->id,
// 'user_id' => $user->id,
// 'expire_date' => Carbon::create($expiryDate),
// 'expired' => false
// ]);
// break;
// case PAYMENT_DECLINED:
// case PAYMENT_REFUNDED:
// if (isset($trans->supporter)) {
// $trans->supporter->expired = true;
// $trans->supporter->save();
// }
// break;
// }
// } else if ($webhook->isTypeOfRecurringPayment()) {
// /**
// * @var RecurringPaymentSubject
// */
// $subject = $webhook->getSubject();
// $ref = $subject->getReference();
// $sub = SupporterSubscription::find($ref);

// assert(isset($sub), "Reference {$ref} does not exist on site. Fix manually.");

// switch ($webhook->getType()) {
// case RECURRING_PAYMENT_STARTED:
// case RECURRING_PAYMENT_RENEWED:
// case RECURRING_PAYMENT_CANCELLATION_ABORTED:
// $sub->update(['status' => 'active', 'next_payment_at' => $subject->getNextPaymentAt()]);
// break;
// case RECURRING_PAYMENT_CANCELLATION_REQUESTED:
// $sub->update(['status' => 'cancelled', 'next_payment_at' => null]);
// break;
// }
// }
// }
}
78 changes: 78 additions & 0 deletions backend/app/Http/Controllers/SupporterPackageController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<?php

namespace App\Http\Controllers;

use App\Http\Requests\FilteredRequest;
use App\Http\Resources\BaseResource;
use App\Models\SupporterPackage;
use App\Services\APIService;
use Illuminate\Http\Request;

class SupporterPackageController extends Controller
{
public function __construct() {
$this->authorizeResource(SupporterPackage::class, 'supporter_package');
}

/**
* Display a listing of the resource.
*/
public function index(FilteredRequest $request)
{
$val = $request->val();
return BaseResource::collectionResponse(SupporterPackage::queryGet($val, fn($q) => $q->orderBy('order')));
}

/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
$val = $request->validate([
'name' => 'string|min:1',
'order' => 'int',
'enabled' => 'boolean',
'package_id' => "int|required",
'price' => 'int|required',
'duration_type' => 'in:mo,y,w,d',
'duration_number' => 'int|min:1|max:120',
]);

return SupporterPackage::create($val);
}

/**
* Display the specified resource.
*/
public function show(SupporterPackage $supporterPackage)
{
return $supporterPackage;
}

/**
* Update the specified resource in storage.
*/
public function update(Request $request, SupporterPackage $supporterPackage)
{
$val = $request->validate([
'name' => 'string|min:1|nullable',
'order' => 'int|nullable',
'enabled' => 'boolean|nullable',
'package_id' => "int|nullable",
'price' => 'int|nullable',
'duration_type' => 'in:mo,y,w,d|nullable',
'duration_number' => 'int|min:1|max:120|nullable',
]);

$supporterPackage->update($val);
return $supporterPackage;
}

/**
* Remove the specified resource from storage.
*/
public function destroy(SupporterPackage $supporterPackage)
{
$supporterPackage->delete();
}
}
9 changes: 0 additions & 9 deletions backend/app/Http/Middleware/UserAuth.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,6 @@ public function handle(Request $request, Closure $next)

// Update the last online every 5 minutes or so.
if (isset($user)) {
$signer = new \NitroPaySponsor\Signer(env('NITRO_TOKEN'));

$user->nitroToken = $signer->sign([
'siteId' => '92', // required
'userId' => $user->id, // required
]);

// \Log::info((array)$signer->getUserSubscription($user?->id));

if (!isset($user->last_online) || $user->last_online->diffInSeconds($now) > 60) {
$user->update([
'last_online' => $now,
Expand Down
2 changes: 2 additions & 0 deletions backend/app/Http/Requests/GetModsRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ public function rules()
'categories.*' => 'integer|min:1|nullable',
'block_tags' => 'array|max:10',
'block_tags.*' => 'integer|min:1|nullable',
'exclude_game_ids' => 'array|max:10',
'exclude_game_ids.*' => 'integer|min:1|nullable',
'user_id' => 'integer|nullable|min:1',
'collab' => 'boolean|nullable',
'including_ignored' => 'boolean|nullable',
Expand Down
37 changes: 0 additions & 37 deletions backend/app/Jobs/CheckUsersSubscriptionStatus.php

This file was deleted.

4 changes: 4 additions & 0 deletions backend/app/Models/Supporter.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,8 @@ public function user(): BelongsTo
{
return $this->belongsTo(User::class)->without('supporter');
}

public function supporterTransaction() {
return $this->hasOne(SupporterTransaction::class);
}
}
14 changes: 14 additions & 0 deletions backend/app/Models/SupporterPackage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class SupporterPackage extends Model
{
protected $guarded = [];

public function getMorphClass(): string {
return 'supporter_package';
}
}
18 changes: 18 additions & 0 deletions backend/app/Models/SupporterSubscription.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class SupporterSubscription extends Model
{
protected $guarded = [];

public function supporter() {
return $this->belongsTo(Supporter::class);
}

public function user() {
return $this->hasOne(User::class);
}
}
18 changes: 18 additions & 0 deletions backend/app/Models/SupporterTransaction.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class SupporterTransaction extends Model
{
protected $guarded = [];

public function supporter() {
return $this->belongsTo(Supporter::class);
}

public function user() {
return $this->hasOne(User::class);
}
}
Loading