Merge branch 'release/1.10.12'

This commit is contained in:
Andy Miller
2021-04-15 12:01:34 -06:00
4 changed files with 188 additions and 29 deletions

View File

@@ -1,8 +1,16 @@
# v1.10.12
## 04/15/2021
1. [](#bugfix)
* Regression: Fixed broken plugin/theme installer in admin
* Fixed error reporting for AJAX tasks if user has no permissions
* Fixed missing slash in password reset URL [#2119](https://github.com/getgrav/grav-plugin-admin/issues/2119)
# v1.10.11 # v1.10.11
## 04/13/2021 ## 04/13/2021
1. [](#bugfix) 1. [](#bugfix)
* **IMPORTANT** Fixed security vulnerability that allows installation of plugins with minimal admin privileges (GHSA-wg37-cf5x-55hq)[https://github.com/getgrav/grav-plugin-admin/security/advisories/GHSA-wg37-cf5x-55hq] * **IMPORTANT** Fixed security vulnerability that allows installation of plugins with minimal admin privileges [GHSA-wg37-cf5x-55hq](https://github.com/getgrav/grav-plugin-admin/security/advisories/GHSA-wg37-cf5x-55hq)
* Fixed `You have been logged out` message when entering to 2FA authentication due to `/admin/task:getNotifications` AJAX call * Fixed `You have been logged out` message when entering to 2FA authentication due to `/admin/task:getNotifications` AJAX call
* Fixed broken 2FA login when site is not configured to use Flex Users [#2109](https://github.com/getgrav/grav-plugin-admin/issues/2109) * Fixed broken 2FA login when site is not configured to use Flex Users [#2109](https://github.com/getgrav/grav-plugin-admin/issues/2109)
* Fixed error message when user clicks logout link after the session has been expired * Fixed error message when user clicks logout link after the session has been expired

View File

@@ -1,7 +1,7 @@
name: Admin Panel name: Admin Panel
slug: admin slug: admin
type: plugin type: plugin
version: 1.10.11 version: 1.10.12
description: Adds an advanced administration panel to manage your site description: Adds an advanced administration panel to manage your site
icon: empire icon: empire
author: author:

View File

@@ -76,6 +76,8 @@ class AdminController extends AdminBaseController
/** /**
* Keep alive * Keep alive
* *
* Route: POST /task:keepAlive (AJAX call)
*
* @return void * @return void
*/ */
protected function taskKeepAlive(): void protected function taskKeepAlive(): void
@@ -89,11 +91,18 @@ class AdminController extends AdminBaseController
/** /**
* Clear the cache. * Clear the cache.
* *
* Route: GET /cache.json/task:clearCache (AJAX call)
*
* @return bool True if the action was performed. * @return bool True if the action was performed.
*/ */
protected function taskClearCache() protected function taskClearCache()
{ {
if (!$this->authorizeTask('clear cache', ['admin.cache', 'admin.maintenance', 'admin.super'])) { if (!$this->authorizeTask('clear cache', ['admin.cache', 'admin.maintenance', 'admin.super'])) {
$this->admin->json_response = [
'status' => 'error',
'message' => $this->admin::translate('PLUGIN_ADMIN.INSUFFICIENT_PERMISSIONS_FOR_TASK')
];
return false; return false;
} }
@@ -133,6 +142,10 @@ class AdminController extends AdminBaseController
/** /**
* Handles form and saves the input data if its valid. * Handles form and saves the input data if its valid.
* *
* Route: POST /pages?task:save
* Route: POST /user?task:save
* Route: POST /*?task:save
*
* @return bool True if the action was performed. * @return bool True if the action was performed.
*/ */
public function taskSave() public function taskSave()
@@ -203,6 +216,9 @@ class AdminController extends AdminBaseController
/** /**
* Handle logout. * Handle logout.
* *
* Route: GET /task:logout
* Route: POST ?task=logout
*
* @return bool True if the action was performed. * @return bool True if the action was performed.
*/ */
protected function taskLogout() protected function taskLogout()
@@ -215,11 +231,18 @@ class AdminController extends AdminBaseController
} }
/** /**
* Route: POST /ajax.json/task:regenerate2FASecret (AJAX call)
*
* @return bool * @return bool
*/ */
public function taskRegenerate2FASecret() public function taskRegenerate2FASecret()
{ {
if (!$this->authorizeTask('regenerate 2FA Secret', ['admin.login', 'admin.super'])) { if (!$this->authorizeTask('regenerate 2FA Secret', ['admin.login', 'admin.super'])) {
$this->admin->json_response = [
'status' => 'error',
'message' => $this->admin::translate('PLUGIN_ADMIN.INSUFFICIENT_PERMISSIONS_FOR_TASK')
];
return false; return false;
} }
@@ -333,12 +356,19 @@ class AdminController extends AdminBaseController
/** /**
* Get Notifications * Get Notifications
* *
* @return never-return * Route: POST /task:getNotifications (AJAX call)
*
* @return bool
*/ */
protected function taskGetNotifications(): void protected function taskGetNotifications()
{ {
if (!$this->authorizeTask('dashboard', ['admin.login', 'admin.super'])) { if (!$this->authorizeTask('dashboard', ['admin.login', 'admin.super'])) {
$this->sendJsonResponse(['status' => 'error', 'message' => 'unauthorized']); $this->admin->json_response = [
'status' => 'error',
'message' => $this->admin::translate('PLUGIN_ADMIN.INSUFFICIENT_PERMISSIONS_FOR_TASK')
];
return false;
} }
// do we need to force a reload // do we need to force a reload
@@ -376,11 +406,18 @@ class AdminController extends AdminBaseController
/** /**
* Hide notifications. * Hide notifications.
* *
* Route: POST /notifications.json/task:hideNotification/notification_id:ID (AJAX call)
*
* @return bool True if the action was performed. * @return bool True if the action was performed.
*/ */
protected function taskHideNotification() protected function taskHideNotification()
{ {
if (!$this->authorizeTask('hide notification', ['admin.login', 'admin.super'])) { if (!$this->authorizeTask('hide notification', ['admin.login', 'admin.super'])) {
$this->admin->json_response = [
'status' => 'error',
'message' => $this->admin::translate('PLUGIN_ADMIN.INSUFFICIENT_PERMISSIONS_FOR_TASK')
];
return false; return false;
} }
@@ -412,12 +449,19 @@ class AdminController extends AdminBaseController
/** /**
* Get Newsfeeds * Get Newsfeeds
* *
* @return never-return * Route: POST /ajax.json/task:getNewsFeed (AJAX call)
*
* @return bool
*/ */
protected function taskGetNewsFeed(): void protected function taskGetNewsFeed()
{ {
if (!$this->authorizeTask('dashboard', ['admin.login', 'admin.super'])) { if (!$this->authorizeTask('dashboard', ['admin.login', 'admin.super'])) {
$this->sendJsonResponse(['status' => 'error', 'message' => 'unauthorized']); $this->admin->json_response = [
'status' => 'error',
'message' => $this->admin::translate('PLUGIN_ADMIN.INSUFFICIENT_PERMISSIONS_FOR_TASK')
];
return false;
} }
$refresh = $this->data['refresh'] === 'true' ? true : false; $refresh = $this->data['refresh'] === 'true' ? true : false;
@@ -446,11 +490,18 @@ class AdminController extends AdminBaseController
/** /**
* Handle the backup action * Handle the backup action
* *
* Route: GET /backup.json/id:BACKUP_ID/task:backup (AJAX call)
*
* @return bool True if the action was performed. * @return bool True if the action was performed.
*/ */
protected function taskBackup() protected function taskBackup()
{ {
if (!$this->authorizeTask('backup', ['admin.maintenance', 'admin.super'])) { if (!$this->authorizeTask('backup', ['admin.maintenance', 'admin.super'])) {
$this->admin->json_response = [
'status' => 'error',
'message' => $this->admin::translate('PLUGIN_ADMIN.INSUFFICIENT_PERMISSIONS_FOR_TASK')
];
return false; return false;
} }
@@ -504,11 +555,18 @@ class AdminController extends AdminBaseController
/** /**
* Handle delete backup action * Handle delete backup action
* *
* Route: GET /backup.json/backup:BACKUP_FILE/task:backupDelete (AJAX call)
*
* @return bool * @return bool
*/ */
protected function taskBackupDelete() protected function taskBackupDelete()
{ {
if (!$this->authorizeTask('backup', ['admin.maintenance', 'admin.super'])) { if (!$this->authorizeTask('backup', ['admin.maintenance', 'admin.super'])) {
$this->admin->json_response = [
'status' => 'error',
'message' => $this->admin::translate('PLUGIN_ADMIN.INSUFFICIENT_PERMISSIONS_FOR_TASK')
];
return false; return false;
} }
@@ -546,7 +604,7 @@ class AdminController extends AdminBaseController
/** /**
* Enable a plugin. * Enable a plugin.
* *
* Route: /plugins * Route: GET /plugins/SLUG/task:enable
* *
* @return bool True if the action was performed. * @return bool True if the action was performed.
*/ */
@@ -576,7 +634,7 @@ class AdminController extends AdminBaseController
/** /**
* Disable a plugin. * Disable a plugin.
* *
* Route: /plugins * Route: GET /plugins/SLUG/task:disable
* *
* @return bool True if the action was performed. * @return bool True if the action was performed.
*/ */
@@ -606,7 +664,7 @@ class AdminController extends AdminBaseController
/** /**
* Set the default theme. * Set the default theme.
* *
* Route: /themes * Route: GET /themes/SLUG/task:activate
* *
* @return bool True if the action was performed. * @return bool True if the action was performed.
*/ */
@@ -650,11 +708,18 @@ class AdminController extends AdminBaseController
/** /**
* Handles updating Grav * Handles updating Grav
* *
* Route: GET /update.json/task:updategrav (AJAX call)
*
* @return bool False if user has no permissions. * @return bool False if user has no permissions.
*/ */
public function taskUpdategrav() public function taskUpdategrav()
{ {
if (!$this->authorizeTask('install grav', ['admin.super'])) { if (!$this->authorizeTask('install grav', ['admin.super'])) {
$this->admin->json_response = [
'status' => 'error',
'message' => $this->admin::translate('PLUGIN_ADMIN.INSUFFICIENT_PERMISSIONS_FOR_TASK')
];
return false; return false;
} }
@@ -684,12 +749,8 @@ class AdminController extends AdminBaseController
/** /**
* Handles uninstalling plugins and themes * Handles uninstalling plugins and themes
* *
* Route: /plugins
* Route: /themes
*
* @deprecated
*
* @return bool True if the action was performed * @return bool True if the action was performed
* @deprecated Not being used anymore
*/ */
public function taskUninstall() public function taskUninstall()
{ {
@@ -720,11 +781,18 @@ class AdminController extends AdminBaseController
/** /**
* Toggle the gpm.releases setting * Toggle the gpm.releases setting
* *
* Route: POST /ajax.json/task:gpmRelease (AJAX call)
*
* @return bool * @return bool
*/ */
protected function taskGpmRelease() protected function taskGpmRelease()
{ {
if (!$this->authorizeTask('configuration', ['admin.super'])) { if (!$this->authorizeTask('configuration', ['admin.super'])) {
$this->admin->json_response = [
'status' => 'error',
'message' => $this->admin::translate('PLUGIN_ADMIN.INSUFFICIENT_PERMISSIONS_FOR_TASK')
];
return false; return false;
} }
@@ -763,6 +831,8 @@ class AdminController extends AdminBaseController
/** /**
* Get update status from GPM * Get update status from GPM
* *
* Request: POST /update.json/task:getUpdates (AJAX call)
*
* @return bool * @return bool
*/ */
protected function taskGetUpdates() protected function taskGetUpdates()
@@ -772,6 +842,11 @@ class AdminController extends AdminBaseController
} }
if (!$this->authorizeTask('dashboard', ['admin.plugins', 'admin.themes', 'admin.super'])) { if (!$this->authorizeTask('dashboard', ['admin.plugins', 'admin.themes', 'admin.super'])) {
$this->admin->json_response = [
'status' => 'error',
'message' => $this->admin::translate('PLUGIN_ADMIN.INSUFFICIENT_PERMISSIONS_FOR_TASK')
];
return false; return false;
} }
@@ -835,13 +910,26 @@ class AdminController extends AdminBaseController
} }
/** /**
* Handle getting a new package dependencies needed to be installed * Handle getting a new package dependencies needed to be installed.
*
* Route: /plugins.json/task:getPackagesDependencies (AJAX call)
* Route: /themes.json/task:getPackagesDependencies (AJAX call)
* *
* @return bool * @return bool
*/ */
protected function taskGetPackagesDependencies() protected function taskGetPackagesDependencies()
{ {
if (!$this->authorizeTask('dashboard', ['admin.plugins', 'admin.themes', 'admin.super'])) { $type = $this->view;
if ($type !== 'plugins' && $type !== 'themes') {
return false;
}
if (!$this->authorizeTask('get package dependencies', ['admin.' . $type, 'admin.super'])) {
$this->admin->json_response = [
'status' => 'error',
'message' => $this->admin::translate('PLUGIN_ADMIN.INSUFFICIENT_PERMISSIONS_FOR_TASK')
];
return false; return false;
} }
@@ -868,17 +956,19 @@ class AdminController extends AdminBaseController
} }
/** /**
* Route: /plugins.json/task:installDependenciesOfPackages (AJAX call)
* Route: /themes.json/task:installDependenciesOfPackages (AJAX call)
*
* @return bool * @return bool
*/ */
protected function taskInstallDependenciesOfPackages() protected function taskInstallDependenciesOfPackages()
{ {
$data = $this->post; $type = $this->view;
$type = $data['type'] ?? '';
if ($type !== 'plugins' && $type !== 'themes') { if ($type !== 'plugins' && $type !== 'themes') {
return false; return false;
} }
if (!$this->authorizeTask('install ' . $type, ['admin.' . $type, 'admin.super'])) { if (!$this->authorizeTask('install dependencies', ['admin.' . $type, 'admin.super'])) {
$this->admin->json_response = [ $this->admin->json_response = [
'status' => 'error', 'status' => 'error',
'message' => $this->admin::translate('PLUGIN_ADMIN.INSUFFICIENT_PERMISSIONS_FOR_TASK') 'message' => $this->admin::translate('PLUGIN_ADMIN.INSUFFICIENT_PERMISSIONS_FOR_TASK')
@@ -887,6 +977,7 @@ class AdminController extends AdminBaseController
return false; return false;
} }
$data = $this->post;
$packages = isset($data['packages']) ? explode(',', $data['packages']) : ''; $packages = isset($data['packages']) ? explode(',', $data['packages']) : '';
$packages = (array)$packages; $packages = (array)$packages;
@@ -917,13 +1008,15 @@ class AdminController extends AdminBaseController
} }
/** /**
* Route: /plugins.json/task:installPackage (AJAX call)
* Route: /themes.json/task:installPackage (AJAX call)
*
* @param bool $reinstall * @param bool $reinstall
* @return bool * @return bool
*/ */
protected function taskInstallPackage($reinstall = false) protected function taskInstallPackage($reinstall = false)
{ {
$data = $this->post; $type = $this->view;
$type = $data['type'] ?? '';
if ($type !== 'plugins' && $type !== 'themes') { if ($type !== 'plugins' && $type !== 'themes') {
return false; return false;
} }
@@ -937,6 +1030,7 @@ class AdminController extends AdminBaseController
return false; return false;
} }
$data = $this->post;
$package = $data['package'] ?? ''; $package = $data['package'] ?? '';
try { try {
$result = Gpm::install($package, ['theme' => $type === 'theme']); $result = Gpm::install($package, ['theme' => $type === 'theme']);
@@ -973,12 +1067,14 @@ class AdminController extends AdminBaseController
/** /**
* Handle removing a package * Handle removing a package
* *
* Route: /plugins.json/task:removePackage (AJAX call)
* Route: /themes.json/task:removePackage (AJAX call)
*
* @return bool * @return bool
*/ */
protected function taskRemovePackage(): bool protected function taskRemovePackage(): bool
{ {
$data = $this->post; $type = $this->view;
$type = $data['type'] ?? '';
if ($type !== 'plugins' && $type !== 'themes') { if ($type !== 'plugins' && $type !== 'themes') {
return false; return false;
} }
@@ -992,6 +1088,7 @@ class AdminController extends AdminBaseController
$this->sendJsonResponse($json_response, 403); $this->sendJsonResponse($json_response, 403);
} }
$data = $this->post;
$package = $data['package'] ?? ''; $package = $data['package'] ?? '';
$result = false; $result = false;
@@ -1046,12 +1143,14 @@ class AdminController extends AdminBaseController
/** /**
* Handle reinstalling a package * Handle reinstalling a package
* *
* Route: /plugins.json/task:reinstallPackage (AJAX call)
* Route: /themes.json/task:reinstallPackage (AJAX call)
*
* @return bool * @return bool
*/ */
protected function taskReinstallPackage() protected function taskReinstallPackage()
{ {
$data = $this->post; $type = $this->view;
$type = $data['type'] ?? '';
if ($type !== 'plugins' && $type !== 'themes') { if ($type !== 'plugins' && $type !== 'themes') {
return false; return false;
} }
@@ -1065,6 +1164,7 @@ class AdminController extends AdminBaseController
$this->sendJsonResponse($json_response, 403); $this->sendJsonResponse($json_response, 403);
} }
$data = $this->post;
$slug = $data['slug'] ?? ''; $slug = $data['slug'] ?? '';
$package_name = $data['package_name'] ?? ''; $package_name = $data['package_name'] ?? '';
$current_version = $data['current_version'] ?? ''; $current_version = $data['current_version'] ?? '';
@@ -1092,6 +1192,8 @@ class AdminController extends AdminBaseController
/** /**
* Handle direct install. * Handle direct install.
* *
* Request: POST /tools/direct-install?task=directInstall
*
* @return bool * @return bool
*/ */
protected function taskDirectInstall() protected function taskDirectInstall()
@@ -1730,6 +1832,11 @@ class AdminController extends AdminBaseController
} }
if (!$this->authorizeTask('get childtypes', ['admin.pages', 'admin.super'])) { if (!$this->authorizeTask('get childtypes', ['admin.pages', 'admin.super'])) {
$this->admin->json_response = [
'status' => 'error',
'message' => $this->admin::translate('PLUGIN_ADMIN.INSUFFICIENT_PERMISSIONS_FOR_TASK')
];
return false; return false;
} }
@@ -1779,6 +1886,11 @@ class AdminController extends AdminBaseController
} }
if (!$this->authorizeTask('filter pages', ['admin.pages', 'admin.super'])) { if (!$this->authorizeTask('filter pages', ['admin.pages', 'admin.super'])) {
$this->admin->json_response = [
'status' => 'error',
'message' => $this->admin::translate('PLUGIN_ADMIN.INSUFFICIENT_PERMISSIONS_FOR_TASK')
];
return false; return false;
} }
@@ -1909,6 +2021,11 @@ class AdminController extends AdminBaseController
protected function taskProcessMarkdown() protected function taskProcessMarkdown()
{ {
if (!$this->authorizeTask('process markdown', ['admin.pages', 'admin.super'])) { if (!$this->authorizeTask('process markdown', ['admin.pages', 'admin.super'])) {
$this->admin->json_response = [
'status' => 'error',
'message' => $this->admin::translate('PLUGIN_ADMIN.INSUFFICIENT_PERMISSIONS_FOR_TASK')
];
return false; return false;
} }
@@ -1964,6 +2081,11 @@ class AdminController extends AdminBaseController
} }
if (!$this->authorizeTask('list media', ['admin.pages', 'admin.super'])) { if (!$this->authorizeTask('list media', ['admin.pages', 'admin.super'])) {
$this->admin->json_response = [
'status' => 'error',
'message' => $this->admin::translate('PLUGIN_ADMIN.INSUFFICIENT_PERMISSIONS_FOR_TASK')
];
return false; return false;
} }
@@ -2021,6 +2143,11 @@ class AdminController extends AdminBaseController
} }
if (!$this->authorizeTask('add media', ['admin.pages', 'admin.super'])) { if (!$this->authorizeTask('add media', ['admin.pages', 'admin.super'])) {
$this->admin->json_response = [
'status' => 'error',
'message' => $this->admin::translate('PLUGIN_ADMIN.INSUFFICIENT_PERMISSIONS_FOR_TASK')
];
return false; return false;
} }
@@ -2179,11 +2306,18 @@ class AdminController extends AdminBaseController
} }
/** /**
* Request: POST .json/task:compileScss (AJAX call)
*
* @return bool * @return bool
*/ */
protected function taskCompileScss() protected function taskCompileScss()
{ {
if (!$this->authorizeTask('compile scss', ['admin.plugins', 'admin.super'])) { if (!$this->authorizeTask('compile scss', ['admin.plugins', 'admin.super'])) {
$this->admin->json_response = [
'status' => 'error',
'message' => $this->admin::translate('PLUGIN_ADMIN.INSUFFICIENT_PERMISSIONS_FOR_TASK')
];
return false; return false;
} }
@@ -2212,11 +2346,18 @@ class AdminController extends AdminBaseController
} }
/** /**
* Request: POST .json/task:exportScss (AJAX call)
*
* @return bool * @return bool
*/ */
protected function taskExportScss() protected function taskExportScss()
{ {
if (!$this->authorizeTask('export scss', ['admin.plugins', 'admin.super'])) { if (!$this->authorizeTask('export scss', ['admin.plugins', 'admin.super'])) {
$this->admin->json_response = [
'status' => 'error',
'message' => $this->admin::translate('PLUGIN_ADMIN.INSUFFICIENT_PERMISSIONS_FOR_TASK')
];
return false; return false;
} }
@@ -2252,6 +2393,11 @@ class AdminController extends AdminBaseController
} }
if (!$this->authorizeTask('delete media', ['admin.pages', 'admin.super'])) { if (!$this->authorizeTask('delete media', ['admin.pages', 'admin.super'])) {
$this->admin->json_response = [
'status' => 'error',
'message' => $this->admin::translate('PLUGIN_ADMIN.INSUFFICIENT_PERMISSIONS_FOR_TASK')
];
return false; return false;
} }
@@ -2834,6 +2980,11 @@ class AdminController extends AdminBaseController
protected function taskConvertUrls() protected function taskConvertUrls()
{ {
if (!$this->authorizeTask('access page', ['admin.pages', 'admin.super'])) { if (!$this->authorizeTask('access page', ['admin.pages', 'admin.super'])) {
$this->admin->json_response = [
'status' => 'error',
'message' => $this->admin::translate('PLUGIN_ADMIN.INSUFFICIENT_PERMISSIONS_FOR_TASK')
];
return false; return false;
} }

View File

@@ -123,7 +123,7 @@ abstract class AdminController
$pages = $this->grav['pages']; $pages = $this->grav['pages'];
$admin = $this->getAdmin(); $admin = $this->getAdmin();
return $pages->baseUrl($lang) . $admin->base . trim($route, '/'); return $pages->baseUrl($lang) . $admin->base . $route;
} }
/** /**
@@ -137,7 +137,7 @@ abstract class AdminController
$pages = $this->grav['pages']; $pages = $this->grav['pages'];
$admin = $this->getAdmin(); $admin = $this->getAdmin();
return $pages->baseUrl($lang, true) . $admin->base . trim($route, '/'); return $pages->baseUrl($lang, true) . $admin->base . $route;
} }
/** /**