-
Notifications
You must be signed in to change notification settings - Fork 96
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
NEW AdminController as superclass for /admin/* routed controllers #1836
NEW AdminController as superclass for /admin/* routed controllers #1836
Conversation
993a9c2
to
05aad97
Compare
ae6c47b
to
7d9c9d0
Compare
@@ -31,5 +31,3 @@ | |||
]); | |||
// enable ability to insert anchors | |||
$editorConfig->insertButtonsAfter('sslink', 'anchor'); | |||
|
|||
CMSMenu::remove_menu_class(CMSProfileController::class); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's handled by config in the class itself now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Basically everything in here was just lifted straight from LeftAndMain
- though some small code quality improvements were made here-and-there.
if (static::class === AdminController::class) { | ||
throw new BadMethodCallException('getRequiredPermissions should be called on a subclass'); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to avoid it being called here, since this is explicitly abstract there's no permission for this class (or reason to want one)
// LeftAndMain methods have a top-level uri access | ||
if (static::class === LeftAndMain::class) { | ||
$segment = ''; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A follow-up card will make LeftAndMain
abstract after removing the methods on it that are used from singleton - but for now this has to stay.
public function redirect(string $url, int $code = 302): HTTPResponse | ||
{ | ||
if ($this->getRequest()->isAjax()) { | ||
$response = $this->getResponse(); | ||
$response->addHeader('X-ControllerURL', $url); | ||
if ($this->getRequest()->getHeader('X-Pjax') && !$response->getHeader('X-Pjax')) { | ||
$response->addHeader('X-Pjax', $this->getRequest()->getHeader('X-Pjax')); | ||
} | ||
$newResponse = new LeftAndMain_HTTPResponse( | ||
$response->getBody(), | ||
$response->getStatusCode(), | ||
$response->getStatusDescription() | ||
); | ||
foreach ($response->getHeaders() as $k => $v) { | ||
$newResponse->addHeader($k, $v); | ||
} | ||
$newResponse->setIsFinished(true); | ||
$this->setResponse($newResponse); | ||
// Actual response will be re-requested by client | ||
return $newResponse; | ||
} else { | ||
return parent::redirect($url, $code); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not 100% sure exactly what all of the ramifications of this are - but since it's dealing explicitly with AJAX requests and that's mostly what this method is for, I decided to lift this out of LeftAndMain and into this class.
public function getClientConfig(): array | ||
{ | ||
// Allows the section name to be overridden in config | ||
$name = static::config()->get('section_name') ?: static::class; | ||
// Trim leading/trailing slash to make it easier to concatenate URL | ||
// and use in routing definitions. | ||
$url = trim($this->Link(), '/'); | ||
$clientConfig = [ | ||
'name' => $name, | ||
'url' => $url, | ||
'reactRoutePath' => preg_replace('/^' . preg_quote(AdminRootController::admin_url(), '/') . '/', '', $url), | ||
]; | ||
$this->extend('updateClientConfig', $clientConfig); | ||
return $clientConfig; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is lifted over here so that we can inject links for these controllers into the config that JS gets a hold of.
// Don't allow access if the request hasn't finished being handled and the user can't access this controller | ||
if (!$this->canView() && !$this->getResponse()->isFinished()) { | ||
// Allow subclasses and extensions to redirect somewhere more appropriate | ||
$this->invokeWithExtensions('onInitPermissionFailure'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This lets LeftAndMain do some redirecting it was doing before without making the method abstract (and therefore required on classes that don't need it) and without doing a method_exists()
check which always feels like the wrong move.
// if no alternate menu items have matched, return a permission error | ||
$messageSet = [ | ||
'default' => _t( | ||
__CLASS__ . '.PERMDEFAULT', | ||
"You must be logged in to access the administration area." | ||
), | ||
'alreadyLoggedIn' => _t( | ||
__CLASS__ . '.PERMALREADY', | ||
"I'm sorry, but you can't access that part of the CMS." | ||
), | ||
'logInAgain' => _t( | ||
__CLASS__ . '.PERMAGAIN', | ||
"You have been logged out of the CMS." | ||
), | ||
]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shortened these messages to suit the fact that most of the time these controllers will be handling AJAX requests and therefore there won't be a menu "below" like the old messages suggest.
I considered finding a way to use the longer messages in LeftAndMain specifically, but the context of "there's a form below" is unnecessary because... well, there's a form below. You can see it (or tab to it if you're on a screen reader)
*/ | ||
private static string $url_base = 'admin'; | ||
|
||
/** | ||
* The LeftAndMain child that will be used as the initial panel to display if none is selected (i.e. if you | ||
* visit /admin) | ||
*/ | ||
private static string $default_panel = SecurityAdmin::class; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are just moved from below per our coding standards (i.e. properties before methods)
$classes = CMSMenu::get_cms_classes(null, true, CMSMenu::URL_PRIORITY); | ||
$classes = CMSMenu::get_cms_classes(AdminController::class, true, CMSMenu::URL_PRIORITY); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
null
defaults to LeftAndMain
- we want the new controller as the base class.
if (($arguments = $request->match($pattern, true)) !== false) { | ||
if ($request->match($pattern, true) !== false) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unrelated refactoring since that variable is never used.
@@ -22,6 +22,8 @@ class CMSProfileController extends LeftAndMain | |||
|
|||
private static $tree_class = Member::class; | |||
|
|||
private static $ignore_menuitem = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the config that lets us remove the code from _config.php
code/LeftAndMain.php
Outdated
private static $help_links = [ | ||
'CMS User help' => 'https://userhelp.silverstripe.org/en/5', | ||
'Developer docs' => 'https://docs.silverstripe.org/en/5/', | ||
'Community' => 'https://www.silverstripe.org/', | ||
'Feedback' => 'https://www.silverstripe.org/give-feedback/', | ||
]; | ||
|
||
/** | ||
* The href for the anchor on the Silverstripe logo | ||
* | ||
* @config | ||
* @var string | ||
*/ | ||
private static $application_link = '//www.silverstripe.org/'; | ||
|
||
/** | ||
* The application name | ||
* | ||
* @config | ||
* @var string | ||
*/ | ||
private static $application_name = 'Silverstripe'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved from below, along with searchFilterCache
as well. These were below some methods.
$cmsClassNames = CMSMenu::get_cms_classes(LeftAndMain::class, true, CMSMenu::URL_PRIORITY); | ||
$cmsClassNames = CMSMenu::get_cms_classes(AdminController::class, true, CMSMenu::URL_PRIORITY); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The config itself can be on any AdminController
now.
code/SudoModeController.php
Outdated
@@ -91,7 +89,7 @@ public function activate(HTTPRequest $request): HTTPResponse | |||
return $this->jsonResponse([ | |||
'result' => false, | |||
'message' => _t(__CLASS__ . '.INVALID', 'Incorrect password'), | |||
]); | |||
], 400); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unrelated refactoring - this is an error, so should have an error response code! There's no context in the original PR that created this class for why it was a 200. It looks like it was an oversight.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be 401, context for this is getting password wrong when trying to activate sudo mode.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I hate HTTP response codes lol.
Updated to 401
} | ||
} | ||
|
||
public static function provideJsonSuccess(): array |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This and everything below it was pulled from LeftAndMainTest
.
$admin = $this->objFromFixture(Member::class, 'admin'); | ||
$this->logInAs($admin); | ||
$this->logInWithPermission('ADMIN'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The admin fixture and the logInWithPermission('ADMIN')
user have the same permissions, so no need for the fixture.
@@ -135,65 +128,6 @@ public function testLeftAndMainSubclasses() | |||
$this->assertMatchesRegularExpression('/<body[^>]*>/i', $response->getBody(), "$link should contain <body> tag"); | |||
} | |||
|
|||
public function testCanView() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was testing the wrong thing - it was trying to test canView()
checks by seeing what's in the menu. But the menu actually shouldn't contain CMSProfileController
so this test was passing when it should have failed.
Moved canView check to the new test class, and now actually testing canView instead of the menu.
The menu itself is already tested in this class.
code/SudoModeController.php
Outdated
@@ -91,7 +89,7 @@ public function activate(HTTPRequest $request): HTTPResponse | |||
return $this->jsonResponse([ | |||
'result' => false, | |||
'message' => _t(__CLASS__ . '.INVALID', 'Incorrect password'), | |||
]); | |||
], 400); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be 401, context for this is getting password wrong when trying to activate sudo mode.
7d9c9d0
to
93f9ce2
Compare
There are two commits here:
CMSProfileController
menu itemAdminController
class and wire it upI've also added a bunch of strong typing to the new class and to
AdminRouteController
.I have not added strong typing to
LeftAndMain
though that may happen as part of a follow-up card in this epic.I have not added strong typing to methods which would required extensive trickle-down effects (e.g.
init()
andcanView()
).Issue
admin/*
routing logic fromLeftAndMain
into its own abstract class #1761