Skip to content

Commit

Permalink
Merge pull request #388 from MineTrax/develop
Browse files Browse the repository at this point in the history
v6.0.0
  • Loading branch information
Xinecraft authored Jun 3, 2024
2 parents a37999c + 8e17e70 commit 053dcfe
Show file tree
Hide file tree
Showing 407 changed files with 13,614 additions and 8,556 deletions.
4 changes: 4 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ APP_LOCALE=en
#If you dont want a locale to appear just remove it(transaltions are accepted on our github)
AVAILABLE_LOCALES=en,es,ru,sk,de,pl,uk,hi,it,zh-hk,zh-cn,ja
APP_THEME=default
# Pulse dashboard for health monitoring
PULSE_ENABLED=false

# Dont enable on production
APP_DEBUG=false
Expand Down Expand Up @@ -42,6 +44,7 @@ VERIFY_USER_EMAIL=false
PLAYER_SKIN_CHANGER_ENABLED=true
PLAYER_SKIN_CHANGER_COOLDOWN_IN_SECONDS=60
HIDE_COUNTRY_FOR_PRIVACY=false
HIDE_PLAYER_NEXT_RANK=false
MAX_USER_PROFILE_PHOTO_SIZE_KB=512
MAX_USER_COVER_PHOTO_SIZE_KB=1024
MAX_POST_FEED_MEDIA_SIZE_KB=1024
Expand Down Expand Up @@ -133,6 +136,7 @@ MAXMIND_LICENSE_KEY=
RATELIMIT_API_PER_MINUTE=600
USE_LEGACY_FTP_DRIVER=false
MARK_USER_VERIFYED_ON_ACCOUNT_LINK=true
DISABLE_PLAYER_UNLINKING=false
USE_USERNAME_FOR_SKINS=false
FETCH_AVATAR_FROM_URL_USING_CURL=false
PLAYER_FETCHER_CRON_INTERVAL=everyThirtyMinutes
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ MineTrax has lot of features, some of them are listed below:

## Upcoming
- Ban Management System
- Staff Recruitment System
- Application System (for staff recruitment and other applications)
- Store System
- Automated Server Events
- Rewards & Achievements
Expand Down
2 changes: 2 additions & 0 deletions app/Console/Kernel.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use App\Console\Commands\ResetUserPasswordCommand;
use App\Jobs\CalculatePlayersJob;
use App\Jobs\RunAwaitingCommandQueuesJob;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;

Expand All @@ -27,6 +28,7 @@ protected function schedule(Schedule $schedule)
{
$playerFetcherInterval = config('minetrax.players_fetcher_cron_interval') ?? 'hourly';
$schedule->job(new CalculatePlayersJob)->{$playerFetcherInterval}();
$schedule->job(new RunAwaitingCommandQueuesJob)->everyMinute();

$schedule->command('telescope:prune')->daily();
$schedule->command('queue:prune-batches --hours=48 --unfinished=72')->daily();
Expand Down
28 changes: 28 additions & 0 deletions app/Enums/CommandQueueStatus.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace App\Enums;

use BenSampo\Enum\Enum;

final class CommandQueueStatus extends Enum
{
const PENDING = 'pending';

const RUNNING = 'running';

const FAILED = 'failed';

const CANCELLED = 'cancelled';

const DEFERRED = 'deferred';

const COMPLETED = 'completed';

public function toArray(): mixed
{
return [
'key' => $this->key,
'value' => $this->value,
];
}
}
65 changes: 17 additions & 48 deletions app/Http/Controllers/AccountLinkController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,73 +2,39 @@

namespace App\Http\Controllers;

use App\Jobs\AccountLinkAfterSuccessCommandJob;
use App\Jobs\AccountUnlinkAfterSuccessCommandJob;
use App\Models\Player;
use App\Models\Server;
use App\Settings\PluginSettings;
use App\Utils\Helpers\AccountLinkUtils;
use Illuminate\Http\Request;
use Inertia\Inertia;

class AccountLinkController extends Controller
{
public function verify($uuid, Server $server, Request $request, PluginSettings $pluginSettings): \Illuminate\Http\RedirectResponse
{
if (! $request->hasValidSignature()) {
return redirect()->route('home')
->with(['toast' => ['type' => 'danger', 'title' => __('Link expired or invalid!'), 'body' => __('Please request a fresh link and try again.'), 'milliseconds' => 10000]]);
}

// Find player with UUID if not found then tell user to wait for sometime till his player become visible in website
$player = Player::where('uuid', $uuid)->first();
if (! $player) {
return redirect()->route('home')
->with(['toast' => ['type' => 'warning', 'title' => __('Player not found in database!'), 'body' => __('Please wait for sometime for server to update its player database.'), 'milliseconds' => 10000]]);
}

// Player found. check if this player is already linked with a user.
if ($player->users()->count() > 0) {
return redirect()->route('home')
->with(['toast' => ['type' => 'danger', 'title' => __('Player already linked to a user!'), 'body' => __('If you own this user please unlink it from your another account or contact administrator.'), 'milliseconds' => 10000]]);
}

// Check if current user has enough available slot to link the player.
$user = $request->user();
$max_slots = $pluginSettings->max_players_link_per_account; // Total number of players that can be linked to account
if ($user->players()->count() >= $max_slots) {
return redirect()->route('home')
->with(['toast' => ['type' => 'danger', 'title' => __('User already have max :max_slots players linked!', ['max_slots' => $max_slots]), 'body' => __('If you want to link this player please unlink a player.'), 'milliseconds' => 10000]]);
}

// @TODO: All good. return a view to confirm the link.
// return Inertia::render('User/ConfirmLinkUserToPlayer', ['player' => $player]);

$user->players()->attach($player);

// If MARK_USER_VERIFYED_ON_ACCOUNT_LINK is enabled then mark user as verified.
if (config('minetrax.mark_user_verified_on_account_link') && $user->verified_at == null) {
$user->verified_at = now();
$user->save();
}

// Run command to give this player the reward according to Plugin setting if enabled
AccountLinkAfterSuccessCommandJob::dispatch($player, $user->id, $server);

return redirect()->route('linked-player.list')
->with(['toast' => ['type' => 'success', 'title' => __('Played linked successfully!'), 'body' => __('This player is now linked to your account.'), 'milliseconds' => 10000]]);
}

public function listMyPlayers(Request $request, PluginSettings $pluginSettings)
{
$linkedPlayers = $request->user()->players()->with(['country', 'rank:id,name,shortname'])->get();

$currentLinkOtp = AccountLinkUtils::generateOtp($request->user()->id);

$isUnlinkingDisabled = config('minetrax.disable_player_unlinking');

return Inertia::render('User/ListLinkedPlayer', [
'linkedPlayers' => $linkedPlayers,
'maxPlayerPerUser' => $pluginSettings->max_players_link_per_account,
'currentLinkOtp' => $currentLinkOtp,
'isUnlinkingDisabled' => $isUnlinkingDisabled,
]);
}

public function unlink(Player $player, Request $request)
{
$isUnlinkingDisabled = config('minetrax.disable_player_unlinking');
if ($isUnlinkingDisabled) {
return redirect()->back()
->with(['toast' => ['type' => 'danger', 'title' => __('Player unlinking disabled!'), 'body' => __('Player unlinking is disabled by the administrator.'), 'milliseconds' => 10000]]);
}

// Make sure the player is linked to current user who is running to unlink
$user = $request->user();
$userHasPlayer = $user->players()->where('player_id', $player->id)->exists();
Expand All @@ -87,6 +53,9 @@ public function unlink(Player $player, Request $request)
$user->save();
}

// Dispatch unlink after success commands
AccountUnlinkAfterSuccessCommandJob::dispatch($player, $user->id);

// Return redirect back with flash
return redirect()->back()
->with(['toast' => ['type' => 'success', 'title' => __('Played unlinked successfully!'), 'body' => __('Player has been removed from your account.'), 'milliseconds' => 10000]]);
Expand Down
139 changes: 139 additions & 0 deletions app/Http/Controllers/Admin/CommandQueueController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
<?php

namespace App\Http\Controllers\Admin;

use App\Enums\CommandQueueStatus;
use App\Http\Controllers\Controller;
use App\Http\Requests\CreateCommandQueueRequest;
use App\Jobs\RunCommandQueueJob;
use App\Jobs\RunCommandQueuesFromRequestJob;
use App\Models\CommandQueue;
use App\Models\Player;
use App\Models\Server;
use App\Queries\Filters\FilterMultipleFields;
use Illuminate\Http\Request;
use Inertia\Inertia;
use Spatie\QueryBuilder\AllowedFilter;
use Spatie\QueryBuilder\QueryBuilder;

class CommandQueueController extends Controller
{
public function index()
{
$this->authorize('viewAny', CommandQueue::class);

$perPage = request()->input('perPage', 10);
if ($perPage > 100) {
$perPage = 100;
}

$fields = [
'id',
'command_id',
'server_id',
'parsed_command',
'config',
'status',
'execute_at',
'max_attempts',
'attempts',
'last_attempt_at',
'output',
'tag',
'player_uuid',
'user_id',
'player_id',
'created_at',
'updated_at',
];

$commandQueues = QueryBuilder::for(CommandQueue::class)
->with(['server:id,name,hostname', 'player:id,uuid,username'])
->allowedFilters([
...$fields,
'server.name',
'player.username',
AllowedFilter::custom('q', new FilterMultipleFields([
'id',
'parsed_command',
'status',
'output',
'tag',
'player_uuid',
])),
])
->allowedSorts($fields)
->defaultSort('-updated_at')
->simplePaginate($perPage)
->withQueryString();

return Inertia::render('Admin/CommandQueue/IndexCommandQueue', [
'commandQueues' => $commandQueues,
'filters' => request()->all(['perPage', 'sort', 'filter']),
]);
}

public function create()
{
$this->authorize('create', CommandQueue::class);

$servers = Server::select(['id', 'name', 'hostname'])->whereNotNull('webquery_port')->get();
$players = Player::select(['id', 'uuid', 'username'])->get();

return Inertia::render('Admin/CommandQueue/CreateCommandQueue', [
'servers' => $servers,
'players' => $players,
]);
}

public function store(CreateCommandQueueRequest $request)
{
RunCommandQueuesFromRequestJob::dispatch($request->collect(), $request->user()->id);

return redirect()->back()
->with(['toast' => ['type' => 'success', 'title' => __('Commands Scheduled!'), 'body' => __('Commands has been scheduled for execution. Check the status in Command History.'), 'milliseconds' => 5000]]);
}

public function destroy(Request $request)
{
$request->validate([
'id' => 'required|int',
]);

$commandQueue = CommandQueue::findOrFail($request->id);
$this->authorize('delete', $commandQueue);

$commandQueue->delete();

return redirect()->route('admin.command-queue.index')
->with(['toast' => ['type' => 'success', 'title' => __('Deleted!')]]);
}

public function retry(Request $request)
{
$request->validate([
'id' => 'sometimes|required|int',
]);

if ($request->id) {
$commandQueues = CommandQueue::where('id', $request->id)->get();
} else {
$commandQueues = CommandQueue::whereIn('status', [
CommandQueueStatus::FAILED,
CommandQueueStatus::CANCELLED,
])->get();
}

foreach ($commandQueues as $commandQueue) {
if ($request->user()->cannot('retry', $commandQueue)) {
continue;
}
$commandQueue->status = 'pending';
$commandQueue->save();
RunCommandQueueJob::dispatch($commandQueue);
}

return redirect()->route('admin.command-queue.index')
->with(['toast' => ['type' => 'success', 'title' => __('Retried!'), 'body' => __('Command has been queued for retrying! Refresh the page after few seconds to check the status.')]]);
}
}
2 changes: 2 additions & 0 deletions app/Http/Controllers/Admin/CustomFormSubmissionController.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ public function index(Request $request)
->select($fields)
->allowedFilters([
...$fields,
'user.name',
AllowedFilter::custom('q', new FilterMultipleFields(['data'])),
])
->allowedSorts($fields)
Expand Down Expand Up @@ -113,6 +114,7 @@ public function indexArchived(Request $request)
->select($fields)
->allowedFilters([
...$fields,
'user.name',
AllowedFilter::custom('q', new FilterMultipleFields(['data'])),
])
->allowedSorts($fields)
Expand Down
Loading

0 comments on commit 053dcfe

Please sign in to comment.