Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ composer.lock
checksums.json
/.node_cache/
/release/
/backups/
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@
"geoip2/geoip2": "^3.0",
"jenssegers/agent": "^2.6",
"php-di/php-di": "^7.0",
"twig/twig": "^3.0"
"twig/twig": "^3.0",
"druidfi/mysqldump-php": "^2.0"
},
"require-dev": {
"phpstan/phpstan": "1.6.9",
Expand Down
14 changes: 14 additions & 0 deletions core/classes/Core/Util.php
Original file line number Diff line number Diff line change
Expand Up @@ -303,4 +303,18 @@ public static function isCompatible(string $version, string $nameless_version):

return $major == $nameless_major && $minor == $nameless_minor;
}

/**
* Format bytes into a human-readable string.
*
* @param int $bytes Number of bytes to format.
* @return string Formatted string.
*/
public static function formatBytes(int $bytes): string
{
$sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
$factor = floor((strlen($bytes) - 1) / 3);

return sprintf('%.2f', $bytes / pow(1024, $factor)) . $sizes[$factor];
}
}
2 changes: 1 addition & 1 deletion core/classes/Database/DatabaseInitialiser.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ private function initialiseGroups(): void
'group_username_color' => '#ff0000',
'group_username_css' => '',
'admin_cp' => true,
'permissions' => '{"administrator":1,"admincp.core":1,"admincp.core.api":1,"admincp.core.seo":1,"admincp.core.general":1,"admincp.core.avatars":1,"admincp.core.fields":1,"admincp.core.debugging":1,"admincp.core.emails":1,"admincp.core.queue":1,"admincp.core.navigation":1,"admincp.core.announcements":1,"admincp.core.reactions":1,"admincp.core.registration":1,"admincp.core.social_media":1,"admincp.core.terms":1,"admincp.errors":1,"admincp.core.placeholders":1,"admincp.members":1,"admincp.integrations":1,"admincp.integrations.edit":1,"admincp.discord":1,"admincp.minecraft":1,"admincp.minecraft.authme":1,"admincp.minecraft.servers":1,"admincp.minecraft.query_errors":1,"admincp.minecraft.banners":1,"admincp.modules":1,"admincp.pages":1,"admincp.security":1,"admincp.security.acp_logins":1,"admincp.security.template":1,"admincp.styles":1,"admincp.styles.panel_templates":1,"admincp.styles.templates":1,"admincp.styles.templates.edit":1,"admincp.styles.images":1,"admincp.update":1,"admincp.users":1,"admincp.users.edit":1,"admincp.groups":1,"admincp.groups.self":1,"admincp.widgets":1,"modcp.ip_lookup":1,"modcp.punishments":1,"modcp.punishments.warn":1,"modcp.punishments.ban":1,"modcp.punishments.banip":1,"modcp.punishments.revoke":1,"modcp.reports":1,"modcp.profile_banner_reset":1,"usercp.messaging":1,"usercp.signature":1,"admincp.forums":1,"usercp.private_profile":1,"usercp.nickname":1,"usercp.title":1,"usercp.profile_banner":1,"profile.private.bypass":1, "admincp.security.all":1,"admincp.core.hooks":1,"admincp.security.group_sync":1,"admincp.core.emails_mass_message":1,"modcp.punishments.reset_avatar":1,"usercp.gif_avatar":1,"profile.post":1}',
'permissions' => '{"administrator":1,"admincp.core":1,"admincp.core.api":1,"admincp.core.seo":1,"admincp.core.general":1,"admincp.core.avatars":1,"admincp.core.fields":1,"admincp.core.debugging":1,"admincp.core.backups":1."admincp.core.emails":1,"admincp.core.queue":1,"admincp.core.navigation":1,"admincp.core.announcements":1,"admincp.core.reactions":1,"admincp.core.registration":1,"admincp.core.social_media":1,"admincp.core.terms":1,"admincp.errors":1,"admincp.core.placeholders":1,"admincp.members":1,"admincp.integrations":1,"admincp.integrations.edit":1,"admincp.discord":1,"admincp.minecraft":1,"admincp.minecraft.authme":1,"admincp.minecraft.servers":1,"admincp.minecraft.query_errors":1,"admincp.minecraft.banners":1,"admincp.modules":1,"admincp.pages":1,"admincp.security":1,"admincp.security.acp_logins":1,"admincp.security.template":1,"admincp.styles":1,"admincp.styles.panel_templates":1,"admincp.styles.templates":1,"admincp.styles.templates.edit":1,"admincp.styles.images":1,"admincp.update":1,"admincp.users":1,"admincp.users.edit":1,"admincp.groups":1,"admincp.groups.self":1,"admincp.widgets":1,"modcp.ip_lookup":1,"modcp.punishments":1,"modcp.punishments.warn":1,"modcp.punishments.ban":1,"modcp.punishments.banip":1,"modcp.punishments.revoke":1,"modcp.reports":1,"modcp.profile_banner_reset":1,"usercp.messaging":1,"usercp.signature":1,"admincp.forums":1,"usercp.private_profile":1,"usercp.nickname":1,"usercp.profile_banner":1,"profile.private.bypass":1, "admincp.security.all":1,"admincp.core.hooks":1,"admincp.security.group_sync":1,"admincp.core.emails_mass_message":1,"modcp.punishments.reset_avatar":1,"usercp.gif_avatar":1,"profile.post":1}',
'order' => 1,
'staff' => true,
]);
Expand Down
10 changes: 10 additions & 0 deletions core/includes/updates/230.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,16 @@ public function run(): void
Settings::set('discord_widget_theme', $discord_widget_theme, 'Discord Integration');
$this->_cache->eraseAll();

// Add admincp.core.backups permission to Admin group
$admin_group = Group::find(1);
$permissions = json_decode($admin_group->permissions, true);
if (!isset($permissions['admincp.core.backups'])) {
$permissions['admincp.core.backups'] = 1;
DB::getInstance()->update('groups', $admin_group->id, [
'permissions' => json_encode($permissions),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of this can still be removed, We have not updated admin group perms for ages as it already had Adminstrator perm

]);
}

$this->setVersion('2.3.0');
}
};
1 change: 1 addition & 0 deletions core/init.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
ROOT_PATH . '/cache/logs',
ROOT_PATH . '/cache/sitemaps',
ROOT_PATH . '/cache/templates_c',
ROOT_PATH . '/cache/backups',
ROOT_PATH . '/uploads',
ROOT_PATH . '/core/config.php',
];
Expand Down
154 changes: 154 additions & 0 deletions custom/panel_templates/Default/core/backups.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
{include file='header.tpl'}

<body id="page-top">

<!-- Wrapper -->
<div id="wrapper">

<!-- Sidebar -->
{include file='sidebar.tpl'}

<!-- Content Wrapper -->
<div id="content-wrapper" class="d-flex flex-column">

<!-- Main content -->
<div id="content">

<!-- Topbar -->
{include file='navbar.tpl'}

<!-- Begin Page Content -->
<div class="container-fluid">

<!-- Page Heading -->
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">{$DEBUGGING_AND_MAINTENANCE}</h1>
<ol class="breadcrumb float-sm-right">
<li class="breadcrumb-item"><a href="{$PANEL_INDEX}">{$DASHBOARD}</a></li>
<li class="breadcrumb-item active">{$CONFIGURATION}</li>
<li class="breadcrumb-item"><a href="{$BACK_LINK}">{$DEBUGGING_AND_MAINTENANCE}</a></li>
<li class="breadcrumb-item active">{$BACKUPS}</li>
</ol>
</div>

<!-- Update Notification -->
{include file='includes/update.tpl'}

<div class="card shadow mb-4">
<div class="card-body">

<h5 style="display: inline-block; margin-top: 7px; margin-bottom: 7px;">{$BACKUPS}</h5>

<div class="float-right">
<a href="{$CREATE_BACKUP_LINK}" class="btn btn-success">{$CREATE_BACKUP}</a>
<a href="{$BACK_LINK}" class="btn btn-primary">{$BACK}</a>
</div>
<hr />

<!-- Success and Error Alerts -->
{include file='includes/alerts.tpl'}

<div class="card shadow border-left-primary">
<div class="card-body">
<h5><i class="icon fa fa-info-circle"></i> {$INFO}</h5>
{$BACKUPS_INFO}
</div>
</div>

<br />

<!-- Backup Settings -->
<div class="card shadow border-left-info mb-4">
<div class="card-body">
<h5><i class="icon fa fa-cogs"></i> {$BACKUP_SETTINGS}</h5>

<form action="" method="post">
<div class="form-group row">
<div class="col-md-6">
<label for="inputMaxRetention">{$MAX_BACKUP_RETENTION}</label>
<input type="number" name="max_backup_retention" id="inputMaxRetention"
class="form-control" value="{$MAX_BACKUP_RETENTION_VALUE}" min="0" step="1">
<small class="form-text text-muted">{$MAX_BACKUP_RETENTION_INFO}</small>
</div>
<div class="col-md-6">
<label for="inputDailyScheduling">{$DAILY_BACKUP_SCHEDULING}</label>
<select name="daily_backup_scheduling" id="inputDailyScheduling" class="form-control">
<option value="0" {if $DAILY_BACKUP_SCHEDULING_VALUE eq '0'}selected{/if}>{$DISABLED}</option>
<option value="1" {if $DAILY_BACKUP_SCHEDULING_VALUE eq '1'}selected{/if}>{$ENABLED}</option>
</select>
<small class="form-text text-muted">{$DAILY_BACKUP_SCHEDULING_INFO}</small>
</div>
</div>
<div class="form-group">
<input type="hidden" name="token" value="{$TOKEN}">
<input type="hidden" name="action" value="settings">
<input type="submit" class="btn btn-primary" value="{$SUBMIT}">
</div>
</form>
</div>
</div>

<!-- Existing Backups -->
{if isset($EXISTING_BACKUPS) && count($EXISTING_BACKUPS) > 0}
<h5>{$EXISTING}</h5>

<div class="table-responsive">
<table class="table table-striped table-hover">
<thead>
<tr>
<th>{$FILENAME}</th>
<th>{$DATE_CREATED}</th>
<th>{$FILE_SIZE}</th>
{if $CAN_DOWNLOAD}
<th>{$ACTIONS}</th>
{/if}
</tr>
</thead>
<tbody>
{foreach from=$EXISTING_BACKUPS item=backup}
<tr>
<td>{$backup.filename}</td>
<td>{$backup.date}</td>
<td>{$backup.size}</td>
{if $CAN_DOWNLOAD}
<td>
<a href="{$backup.download_link}" target="_blank" class="btn btn-sm btn-primary">
<i class="fa fa-download"></i> {$DOWNLOAD}
</a>
</td>
{/if}
</tr>
{/foreach}
</tbody>
</table>
</div>
{else}
<div class="alert alert-info">
<i class="fa fa-info-circle"></i> {$NO_BACKUPS}
</div>
{/if}
</div>
</div>

<!-- Spacing -->
<div style="height:1rem;"></div>

<!-- End Page Content -->
</div>

<!-- End Main Content -->
</div>

{include file='footer.tpl'}

<!-- End Content Wrapper -->
</div>

<!-- End Wrapper -->
</div>

{include file='scripts.tpl'}

</body>

</html>
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,11 @@
<div class="card shadow mb-4">
<div class="card-body">
{if isset($ERROR_LOGS)}
<a href="{$ERROR_LOGS_LINK}" class="btn btn-primary">{$ERROR_LOGS}</a>
<a href="{$ERROR_LOGS_LINK}" class="btn btn-primary">{$ERROR_LOGS}</a>
{/if}

{if isset($BACKUPS_LINK)}
<a href="{$BACKUPS_LINK}" class="btn btn-primary">{$BACKUPS}</a>
{/if}

<button class="float-right btn btn-info d-flex align-items-center" id="show_debug_modal" onclick="showDebugModal()">
Expand Down
42 changes: 42 additions & 0 deletions custom/panel_templates/Default/core/update.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,48 @@
</ol>
</div>

<!-- Backup Recommendation Card -->
{if isset($NEW_UPDATE) && isset($BACKUP_RECOMMENDATION)}
<div class="card shadow mb-4 border-left-warning">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-warning">
<i class="fas fa-exclamation-triangle"></i> {$BACKUP_RECOMMENDATION}
</h6>
</div>
<div class="card-body">
<p class="mb-3">{$BACKUP_BEFORE_UPDATE}</p>

<div class="row">
<div class="col-md-6">
<h6 class="font-weight-bold">{$MOST_RECENT_BACKUP}</h6>
{if isset($LATEST_BACKUP)}
<div class="alert alert-success">
<i class="fas fa-check-circle"></i>
<strong>{$LATEST_BACKUP.filename}</strong><br>
<small>{$LATEST_BACKUP.date_formatted}</small>
</div>
{else}
<div class="alert alert-warning">
<i class="fas fa-exclamation-triangle"></i>
{$NO_RECENT_BACKUP}
</div>
{/if}
</div>
<div class="col-md-6">
<div class="d-flex flex-column h-100 justify-content-center">
<a href="{$CREATE_BACKUP_LINK}" class="btn btn-success mb-2">
<i class="fas fa-plus"></i> {$CREATE_BACKUP}
</a>
<a href="{$BACKUPS_PAGE_LINK}" class="btn btn-outline-primary">
<i class="fas fa-archive"></i> {$MANAGE_BACKUPS}
</a>
</div>
</div>
</div>
</div>
</div>
{/if}

<div class="card shadow mb-4">
<div class="card-body">
<!-- Success and Error Alerts -->
Expand Down
Loading