You've already forked Atomcms-edit
Low priority fixes: debug comments, Fortify cleanup, badge cost setting, profile query merge, User model fixes, VPN constructor cleanup, PayPal POST, PII removal, Dutch→English translations, duplicate rank check, CHANGELOG
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
# Changelog
|
||||
|
||||
## V3 — 2026-06-04
|
||||
|
||||
### Added
|
||||
- Commandocentrum with Nitro V3 one-click updater
|
||||
- Configurable paths (9 settings) stored in DB via HK UI
|
||||
- Emulator start/stop/restart from admin panel
|
||||
- Live monitoring (online users, DB status, server load)
|
||||
- Hotel alert system
|
||||
- Emulator logs viewer
|
||||
- Clothing sync from FigureMap
|
||||
- Social login (Google, Discord, GitHub)
|
||||
- Staff activity log
|
||||
- Notification settings (email & Discord)
|
||||
- PHP 8.5 + Ubuntu 26.04 support
|
||||
- Dual .env system (Linux + Windows)
|
||||
- Bulletproof 12-step installation guide
|
||||
|
||||
### Changed
|
||||
- Complete README rewrite with badges, tables, quick start
|
||||
- All Dutch comments translated to English
|
||||
- XAMPP support removed (security warning added)
|
||||
- `.env.example` → `.env.install` with step-by-step guide
|
||||
- `.env.standard` → `.env.example.linux` + `.env.example.windows`
|
||||
|
||||
### Fixed
|
||||
- Removed debug comments from config/app.php
|
||||
- Removed commented Fortify features
|
||||
- Badge cost now configurable via `setting('badge_cost', 150)`
|
||||
- ProfileController: merged 2 setting queries into 1
|
||||
- User model: removed `save()` override that broke Eloquent expectations
|
||||
- User model: removed `id` from `$hidden` (was inconsistent with API exposure)
|
||||
- VPNCheckerMiddleware: removed empty constructor argument
|
||||
- PayPal process route: GET → POST
|
||||
- Discord webhook: no longer sends PII (email/IP)
|
||||
- API purchase: added rank duplicate check
|
||||
@@ -171,13 +171,11 @@ class CreateNewUser implements CreatesNewUsers
|
||||
try {
|
||||
Http::asJson()->post(is_string($discordWebhookUrl) ? $discordWebhookUrl : '', [
|
||||
'username' => sprintf('%s Bot', is_string($hotelNameSetting) ? $hotelNameSetting : 'Hotel'),
|
||||
'content' => "User: {$username} has just registered, with the IP: {$ip} and E-mail: {$email}",
|
||||
'content' => "User: {$username} has just registered.",
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Failed to send Discord webhook notification', [
|
||||
'username' => $username,
|
||||
'ip' => $ip,
|
||||
'email' => $email,
|
||||
'error' => $e->getMessage(),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -317,6 +317,10 @@ class HotelApiController extends Controller
|
||||
|
||||
$user = $request->user();
|
||||
|
||||
if ($package->give_rank && $user->rank >= $package->give_rank) {
|
||||
return response()->json(['error' => 'You already have this or a higher rank'], 400);
|
||||
}
|
||||
|
||||
$cost = $package->costs;
|
||||
|
||||
if ($user->credits < $cost) {
|
||||
|
||||
@@ -12,7 +12,7 @@ class BadgeController extends Controller
|
||||
{
|
||||
public function show(): View
|
||||
{
|
||||
$cost = 150;
|
||||
$cost = (int) setting('badge_cost', 150);
|
||||
$currencyType = 'credits';
|
||||
$folderError = false;
|
||||
$errorMessage = '';
|
||||
@@ -60,7 +60,7 @@ class BadgeController extends Controller
|
||||
return redirect()->route('login')->with('error', 'You must be logged in to purchase badges.');
|
||||
}
|
||||
|
||||
$cost = 150;
|
||||
$cost = (int) setting('badge_cost', 150);
|
||||
|
||||
if (property_exists($user, 'credits') && $user->credits !== null && $user->credits < $cost) {
|
||||
return redirect()->back()->with('error', 'You don\'t have enough credits to purchase a badge.');
|
||||
|
||||
@@ -20,8 +20,10 @@ class ProfileController extends Controller
|
||||
'badges',
|
||||
]);
|
||||
|
||||
$showStats = (bool) (WebsiteSetting::where('key', 'profile_show_stats')->first()?->value ?? '1');
|
||||
$showOnline = (bool) (WebsiteSetting::where('key', 'profile_show_online_status')->first()?->value ?? '1');
|
||||
$settings = WebsiteSetting::whereIn('key', ['profile_show_stats', 'profile_show_online_status'])
|
||||
->pluck('value', 'key');
|
||||
$showStats = (bool) ($settings['profile_show_stats'] ?? '1');
|
||||
$showOnline = (bool) ($settings['profile_show_online_status'] ?? '1');
|
||||
|
||||
return view('user.profile', [
|
||||
'user' => $user,
|
||||
|
||||
@@ -17,7 +17,7 @@ class RadioApiKey
|
||||
|
||||
if (empty($key)) {
|
||||
return response()->json([
|
||||
'error' => 'API key is verplicht. Gebruik Authorization: Bearer <key> of ?api_key=<key>',
|
||||
'error' => 'API key is required. Use Authorization: Bearer <key> or ?api_key=<key>',
|
||||
], 401);
|
||||
}
|
||||
|
||||
@@ -25,19 +25,19 @@ class RadioApiKey
|
||||
|
||||
if (! $apiKey) {
|
||||
return response()->json([
|
||||
'error' => 'API key is ongeldig of verlopen',
|
||||
'error' => 'API key is invalid or expired',
|
||||
], 401);
|
||||
}
|
||||
|
||||
if (! $apiKey->isAllowedIp($request->ip())) {
|
||||
return response()->json([
|
||||
'error' => 'IP-adres niet toegestaan voor deze API key',
|
||||
'error' => 'IP address not allowed for this API key',
|
||||
], 403);
|
||||
}
|
||||
|
||||
if (! $apiKey->hasPermission($permission)) {
|
||||
return response()->json([
|
||||
'error' => 'Geen toestemming voor deze actie',
|
||||
'error' => 'No permission for this action',
|
||||
], 403);
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ class VPNCheckerMiddleware
|
||||
return $this->denyAccess($request);
|
||||
}
|
||||
|
||||
$ipService = new IpLookupService('');
|
||||
$ipService = new IpLookupService;
|
||||
|
||||
$countryInfo = $ipService->getCountryInfo($userIp);
|
||||
|
||||
|
||||
+1
-14
@@ -128,7 +128,7 @@ class User extends Authenticatable implements FilamentUser, HasName
|
||||
protected $fillable = ['username', 'mail', 'password', 'account_created', 'last_login', 'motto', 'look', 'credits', 'last_username_change', 'auth_ticket', 'home_room', 'ip_register', 'ip_current', 'referral_code', 'preferences', 'team_id', 'avatar_background', 'home_background', 'pincode', 'secret_key', 'extra_rank', 'is_hidden', 'background_id', 'background_stand_id', 'background_overlay_id', 'radio_points', 'pixels', 'points', 'online', 'gender', 'rank', 'mail_verified', 'two_factor_secret', 'two_factor_recovery_codes', 'two_factor_confirmed_at'];
|
||||
|
||||
#[\Override]
|
||||
protected $hidden = ['id', 'password', 'remember_token'];
|
||||
protected $hidden = ['password', 'remember_token'];
|
||||
|
||||
/**
|
||||
* @return array<string, string>
|
||||
@@ -394,19 +394,6 @@ class User extends Authenticatable implements FilamentUser, HasName
|
||||
->logOnlyDirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $options
|
||||
*/
|
||||
#[\Override]
|
||||
public function save(array $options = []): bool
|
||||
{
|
||||
if (! $this->isDirty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return parent::save($options);
|
||||
}
|
||||
|
||||
public function hasAppliedForTeam(int $teamId): bool
|
||||
{
|
||||
if ($teamId === 0) {
|
||||
|
||||
+1
-3
@@ -2,7 +2,6 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
// Auto-push test
|
||||
use App\Providers\AppServiceProvider;
|
||||
use App\Providers\EventServiceProvider;
|
||||
use App\Providers\Filament\AdminFilamentPanelProvider;
|
||||
@@ -247,5 +246,4 @@ return [
|
||||
// 'ExampleClass' => App\Example\ExampleClass::class,
|
||||
])->toArray(),
|
||||
|
||||
];
|
||||
// test
|
||||
]
|
||||
|
||||
@@ -147,14 +147,9 @@ return [
|
||||
|
||||
'features' => [
|
||||
Features::registration(),
|
||||
// Features::resetPasswords(),
|
||||
// Features::emailVerification(),
|
||||
// Features::updateProfileInformation(),
|
||||
// Features::updatePasswords(),
|
||||
Features::twoFactorAuthentication([
|
||||
'confirm' => true,
|
||||
'confirmPassword' => true,
|
||||
// 'window' => 0,
|
||||
]),
|
||||
],
|
||||
|
||||
|
||||
+13
-13
@@ -1,4 +1,4 @@
|
||||
# Uitgebreide PHP locatie detector voor IIS web.config
|
||||
# Extended PHP location detector for IIS web.config
|
||||
|
||||
$searchPaths = @(
|
||||
"C:\PHP",
|
||||
@@ -19,11 +19,11 @@ $searchPaths = @(
|
||||
|
||||
$phpPath = $null
|
||||
|
||||
# Methode 1: Check of php-cgi.exe in PATH staat
|
||||
Write-Host "Zoeken naar php-cgi.exe..." -ForegroundColor Cyan
|
||||
# Method 1: Check if php-cgi.exe is in PATH
|
||||
Write-Host "Searching for php-cgi.exe..." -ForegroundColor Cyan
|
||||
$phpPath = (Get-Command php-cgi.exe -ErrorAction SilentlyContinue).Source
|
||||
|
||||
# Methode 2: Zoek in standaard locaties
|
||||
# Method 2: Search in default locations
|
||||
if (-not $phpPath) {
|
||||
foreach ($basePath in $searchPaths) {
|
||||
if (Test-Path $basePath) {
|
||||
@@ -37,9 +37,9 @@ if (-not $phpPath) {
|
||||
}
|
||||
}
|
||||
|
||||
# Methode 3: Zoek in alle C: schijf (alleen top-level folders voor snelheid)
|
||||
# Method 3: Search entire C: drive (top-level folders only for speed)
|
||||
if (-not $phpPath) {
|
||||
Write-Host "Zoeken in C:\ schijf..." -ForegroundColor Yellow
|
||||
Write-Host "Searching C:\ drive..." -ForegroundColor Yellow
|
||||
$rootFolders = Get-ChildItem -Path "C:\" -Directory -ErrorAction SilentlyContinue |
|
||||
Where-Object { $_.Name -match 'php|wamp|laragon|inetpub' }
|
||||
foreach ($folder in $rootFolders) {
|
||||
@@ -52,7 +52,7 @@ if (-not $phpPath) {
|
||||
}
|
||||
}
|
||||
|
||||
# Methode 4: Check Windows Registry voor PHP installaties
|
||||
# Method 4: Check Windows Registry for PHP installations
|
||||
if (-not $phpPath) {
|
||||
$regPaths = @(
|
||||
"HKLM:\SOFTWARE\PHP",
|
||||
@@ -73,7 +73,7 @@ if (-not $phpPath) {
|
||||
}
|
||||
|
||||
if ($phpPath) {
|
||||
Write-Host "`nGevonden: $phpPath" -ForegroundColor Green
|
||||
Write-Host "`nFound: $phpPath" -ForegroundColor Green
|
||||
|
||||
$webConfigPath = ".\web.config"
|
||||
if (Test-Path $webConfigPath) {
|
||||
@@ -82,14 +82,14 @@ if ($phpPath) {
|
||||
|
||||
if ($content -ne $newContent) {
|
||||
$newContent | Set-Content $webConfigPath -NoNewline
|
||||
Write-Host "Handler succesvol geupdate in web.config!" -ForegroundColor Green
|
||||
Write-Host "Handler successfully updated in web.config!" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host "Handler was al correct ingesteld." -ForegroundColor Yellow
|
||||
Write-Host "Handler was already set correctly." -ForegroundColor Yellow
|
||||
}
|
||||
} else {
|
||||
Write-Host "web.config niet gevonden in huidige directory!" -ForegroundColor Red
|
||||
Write-Host "web.config not found in current directory!" -ForegroundColor Red
|
||||
}
|
||||
} else {
|
||||
Write-Host "`nKon php-cgi.exe niet vinden." -ForegroundColor Red
|
||||
Write-Host "Controleer of PHP correct is geinstalleerd." -ForegroundColor Red
|
||||
Write-Host "`nCould not find php-cgi.exe." -ForegroundColor Red
|
||||
Write-Host "Check if PHP is installed correctly." -ForegroundColor Red
|
||||
}
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ Route::prefix('shop')->group(function () {
|
||||
|
||||
// PayPal routes
|
||||
Route::controller(PayPalController::class)->prefix('paypal')->group(function () {
|
||||
Route::get('/process-transaction', 'process')->name('paypal.process-transaction');
|
||||
Route::post('/process-transaction', 'process')->name('paypal.process-transaction');
|
||||
Route::get('/successful-transaction', 'successful')->name('paypal.successful-transaction');
|
||||
Route::get('/cancelled-transaction', 'cancelled')->name('paypal.cancelled-transaction');
|
||||
});
|
||||
|
||||
+13
-13
@@ -3,7 +3,7 @@
|
||||
# Exit immediately if a command exits with a non-zero status
|
||||
set -e
|
||||
|
||||
# --- CONFIGURATION (overschrijfbaar via omgevingsvariabelen) ---
|
||||
# --- CONFIGURATION (overridable via environment variables) ---
|
||||
DB_NAME="${NITRO_DB_NAME:-habbo}"
|
||||
DB_HOST="${NITRO_DB_HOST:-127.0.0.1}"
|
||||
DB_PORT="${NITRO_DB_PORT:-3306}"
|
||||
@@ -44,7 +44,7 @@ echo "--> Checking for new SQL files..."
|
||||
if [ -d "$SQL_DIR" ]; then
|
||||
find "$SQL_DIR" -name "*.sql" -mmin -10 -print0 | while IFS= read -r -d '' sql_file; do
|
||||
echo "--> Importing new SQL file: $(basename "$sql_file")"
|
||||
mariadb $MYSQL_CRED --force "$DB_NAME" < "$sql_file" || echo "--> Opmerking: Sommige SQL-regels overgeslagen (bestonden waarschijnlijk al)."
|
||||
mariadb $MYSQL_CRED --force "$DB_NAME" < "$sql_file" || echo "--> Note: Some SQL rules skipped (probably already exist)."
|
||||
done
|
||||
else
|
||||
echo "--> SQL directory not found, skipping SQL import."
|
||||
@@ -156,25 +156,25 @@ fi
|
||||
# ----------------------------------------
|
||||
echo "--> Starting automated cleanup..."
|
||||
|
||||
# 1. Verwijder emulator logs ouder dan 14 dagen
|
||||
# 1. Remove emulator logs older than 14 days
|
||||
echo "--> Removing emulator logs older than 14 days..."
|
||||
find "$EMULATOR_DIR/" -name "*.log" -mtime +14 -exec rm -f {} \;
|
||||
|
||||
# 2. Hou maximaal de 5 nieuwste database backups, gooi oudere weg
|
||||
# 2. Keep max 5 newest database backups, delete older ones
|
||||
echo "--> Managing update backups (keeping max 5)..."
|
||||
if [ -d "$BACKUP_DIR" ]; then
|
||||
# Zoekt alle .sql bestanden in de backup map, sorteert op datum (nieuwste eerst),
|
||||
# slaat de eerste 5 over (tail -n +6) en verwijdert de rest.
|
||||
# Find all .sql files in backup dir, sort by date (newest first),
|
||||
# skip the first 5 (tail -n +6) and delete the rest.
|
||||
ls -t "$BACKUP_DIR"/*.sql 2>/dev/null | tail -n +6 | xargs -r rm -f || true
|
||||
fi
|
||||
|
||||
# 3. Clean Yarn cache om SSD ruimte te besparen
|
||||
# 3. Clean Yarn cache to save SSD space
|
||||
echo "--> Cleaning Yarn cache..."
|
||||
yarn cache clean
|
||||
|
||||
|
||||
# ----------------------------------------
|
||||
# 6. Fix Permissions (www-data) — alleen als sudo beschikbaar is
|
||||
# 6. Fix Permissions (www-data) — only if sudo is available
|
||||
# ----------------------------------------
|
||||
if command -v sudo &> /dev/null; then
|
||||
echo "--> Setting permissions to www-data:www-data..."
|
||||
@@ -183,7 +183,7 @@ if command -v sudo &> /dev/null; then
|
||||
sudo chown -R www-data:www-data "$EMULATOR_DIR" 2>/dev/null || echo "--> chown voor EMULATOR_DIR overgeslagen"
|
||||
sudo chown -R www-data:www-data "$GAMEDATA_CONF_DIR" 2>/dev/null || echo "--> chown voor GAMEDATA_CONF_DIR overgeslagen"
|
||||
else
|
||||
echo "--> Sudo niet beschikbaar, overslaan van chown."
|
||||
echo "--> Sudo not available, skipping chown."
|
||||
fi
|
||||
|
||||
|
||||
@@ -193,14 +193,14 @@ fi
|
||||
if systemctl list-units --type=service --all | grep -q "$EMULATOR_SERVICE.service"; then
|
||||
echo "--> Restarting $EMULATOR_SERVICE service..."
|
||||
if command -v sudo &> /dev/null; then
|
||||
sudo systemctl restart $EMULATOR_SERVICE 2>/dev/null || echo "--> Service restart via sudo mislukt (mogelijk geen sudo rechten)"
|
||||
sudo systemctl restart $EMULATOR_SERVICE 2>/dev/null || echo "--> Service restart via sudo failed (possible insufficient sudo rights)"
|
||||
sudo systemctl status $EMULATOR_SERVICE --no-pager -n 5 2>/dev/null || true
|
||||
else
|
||||
echo "--> Sudo niet beschikbaar. Herstart de service handmatig: sudo systemctl restart $EMULATOR_SERVICE"
|
||||
echo "--> Sudo not available. Restart the service manually: sudo systemctl restart $EMULATOR_SERVICE"
|
||||
fi
|
||||
else
|
||||
echo "--> Waarschuwing: Service '$EMULATOR_SERVICE' niet gevonden in systemd."
|
||||
echo "--> Als je PM2 gebruikt, herstart je processen dan handmatig met: pm2 restart all"
|
||||
echo "--> Warning: Service '$EMULATOR_SERVICE' not found in systemd."
|
||||
echo "--> If you use PM2, restart your processes manually: pm2 restart all"
|
||||
fi
|
||||
|
||||
echo "=== Update successfully completed! ==="
|
||||
Reference in New Issue
Block a user