-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
572 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
a.aos-pagelist-confirm + a.aos-pagelist-confirm { | ||
margin-left: 3px; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
// Delete + non-superuser Trash actions | ||
// console.log(ProcessWire.config.AOS_BypassTrash); | ||
$(document).on("mousedown", "a.aos-pagelist-confirm", function (e) { | ||
var str_cancel = ProcessWire.config.AOS_BypassTrash.str_cancel; | ||
var str_confirm = ProcessWire.config.AOS_BypassTrash.str_confirm; | ||
|
||
// console.log(str_cancel); | ||
// console.log(str_confirm); | ||
|
||
e.preventDefault(); | ||
if (e.which === 3 || e.which === 2) return false; | ||
|
||
var link = $(this), | ||
url = link.attr("href"), | ||
linkTextDefault; | ||
|
||
if (!link.attr("data-text-original")) { | ||
var currentText = $(this).get(0).childNodes[1] | ||
? $(this).get(0).childNodes[1].nodeValue | ||
: $(this).html(); | ||
link.attr("data-text-original", currentText); | ||
if (link.hasClass("PageListActionDelete") || link.hasClass("PageDelete")) { | ||
link.attr("data-text-confirm", str_confirm); | ||
} | ||
} | ||
|
||
if (url.indexOf("&force=1") === -1) { | ||
var linkCancel; | ||
linkTextDefault = link.attr("data-text-original"); | ||
|
||
if (link.hasClass("cancel")) { | ||
linkCancel = link.next("a"); | ||
linkCancel | ||
.removeClass("cancel") | ||
.attr("href", link.attr("href").replace("&force=1", "")) | ||
.contents() | ||
.last()[0].textContent = linkTextDefault; | ||
link.replaceWith(linkCancel); | ||
return false; | ||
} | ||
|
||
linkTextDefault = link.attr("data-text-confirm") | ||
? link.attr("data-text-confirm") | ||
: link.attr("data-text-original"); | ||
linkCancel = link.clone(true); | ||
linkCancel.addClass("cancel").contents().last()[0].textContent = " " + str_cancel; | ||
|
||
// replace text only (keep icon) | ||
link.contents().last()[0].textContent = linkTextDefault; | ||
link.attr("href", link.attr("href") + "&force=1"); | ||
link.before(linkCancel); | ||
} | ||
|
||
return false; | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,179 @@ | ||
<?php | ||
|
||
namespace RockAdminTweaks; | ||
|
||
use ProcessWire\HookEvent; | ||
use ProcessWire\Inputfield; | ||
use ProcessWire\RepeaterPage; | ||
|
||
class BypassTrash extends Tweak | ||
{ | ||
private $editedPage; | ||
private $strings; | ||
|
||
|
||
public function info(): array | ||
{ | ||
return [ | ||
'description' => "Add buttons/options, to Page list actions and page edit tab, to bypass trash for SuperUsers", | ||
]; | ||
} | ||
|
||
|
||
public function ready(): void | ||
{ | ||
if (!$this->wire->user->isSuperuser()) { | ||
return; | ||
} | ||
|
||
// Translatable strings | ||
$this->strings = new \StdClass(); | ||
$this->strings->cancel = $this->_("Cancel Deletion"); | ||
$this->strings->confirm = $this->_("Delete Permanently"); | ||
$this->strings->skip_trash = $this->_('Skip Trash?'); | ||
$this->strings->desc = $this->_('Check to permanently delete this page.'); | ||
$this->strings->deleted = $this->_('Deleted page: %s'); | ||
|
||
$this->addHookAfter('ProcessPageListActions::getExtraActions', $this, 'addDeleteButton'); | ||
$this->addHookAfter('ProcessPageListActions::processAction', $this, 'addDeleteButtonAction'); | ||
|
||
// add delete field to page edit Delete tab | ||
$this->addHookAfter('ProcessPageEdit::buildFormDelete', $this, 'addDeletePermanentlyField'); | ||
$this->addHookBefore('Pages::trash', $this, 'addDeletePermanentlyHook'); | ||
|
||
$this->wire->addHookBefore("ProcessPageList::execute", function() { | ||
$str_cancel = $this->strings->cancel; | ||
$str_confirm = $this->strings->confirm; | ||
$this->wire('config')->js('AOS_BypassTrash', compact('str_cancel', 'str_confirm')); | ||
$this->loadCSS(); | ||
$this->loadJS(); | ||
}); | ||
|
||
$this->editedPage = false; | ||
$editedPageId = $this->wire('sanitizer')->int($this->wire('input')->get->id); | ||
$editedPage = $this->wire('pages')->get($editedPageId); | ||
|
||
if ($editedPage->id && !($editedPage instanceof RepeaterPage)) { | ||
$this->editedPage = $editedPage; | ||
} | ||
} | ||
|
||
|
||
/** | ||
* Add Delete button to pagelist | ||
*/ | ||
public function addDeleteButton(HookEvent $event) | ||
{ | ||
$page = $event->arguments('page'); | ||
|
||
if (!$this->wire('user')->isSuperuser()) { | ||
return false; | ||
} | ||
|
||
// do not allow for pages having children | ||
if ($page->numChildren > 0) { | ||
return false; | ||
} | ||
|
||
// not trashable and not in Trash | ||
if (!$page->trashable() && !$page->isTrash()) { | ||
return false; | ||
} | ||
|
||
$actions = array(); | ||
$adminUrl = $this->wire('config')->urls->admin . 'page/'; | ||
$icon = ''; | ||
$actions['delete'] = array( | ||
'cn' => 'Delete aos-pagelist-confirm', | ||
'name' => $icon . 'Delete', | ||
'url' => $adminUrl . '?action=delete&id=' . $page->id, | ||
'ajax' => true, | ||
); | ||
|
||
$event->return += $actions; | ||
} | ||
|
||
|
||
/** | ||
* Process action for addDeleteButton. | ||
* | ||
* @return bool | ||
*/ | ||
public function addDeleteButtonAction(HookEvent $event) | ||
{ | ||
$page = $event->arguments(0); | ||
$action = $event->arguments(1); | ||
// do not allow for pages having children | ||
if ($page->numChildren > 0) { | ||
return false; | ||
} | ||
|
||
if ($action == 'delete') { | ||
$page->delete(); | ||
$event->return = array( | ||
'action' => $action, | ||
'success' => true, | ||
'page' => $page->id, | ||
'updateItem' => $page->id, | ||
'message' => 'Page deleted.', | ||
'remove' => true, | ||
'refreshChildren' => false, | ||
); | ||
} | ||
} | ||
|
||
|
||
public function addDeletePermanentlyField(HookEvent $event) | ||
{ | ||
if ($this->editedPage && !$this->editedPage->trashable()) { | ||
return false; | ||
} | ||
|
||
$form = $event->return; | ||
|
||
$trashConfirmField = $form->get('delete_page'); | ||
if (!$trashConfirmField) { | ||
return false; | ||
} | ||
|
||
$f = $this->wire('modules')->get('InputfieldCheckbox'); | ||
$f->attr('id+name', 'delete_permanently'); | ||
$f->checkboxLabel = $this->strings->confirm; | ||
$f->label = $this->strings->skip_trash; | ||
$f->description = $this->strings->desc; | ||
$f->value = '1'; | ||
|
||
$trashConfirmField->columnWidth = 50; | ||
$f->columnWidth = 50; | ||
|
||
$f->collapsed = Inputfield::collapsedNever; | ||
$trashConfirmField->collapsed = Inputfield::collapsedNever; | ||
|
||
// add fieldset (Reno top spacing bug) | ||
if ($this->adminTheme === 'AdminThemeReno') { | ||
$fset = $this->wire('modules')->get('InputfieldFieldset'); | ||
$fset->add($trashConfirmField); | ||
$fset->add($f); | ||
$form->remove($trashConfirmField); | ||
$form->insertBefore($fset, $form->get('submit_delete')); | ||
} else { | ||
$form->insertAfter($f, $trashConfirmField); | ||
} | ||
} | ||
|
||
|
||
// delete page instead trashing if delete_permanently was checked | ||
public function addDeletePermanentlyHook(HookEvent $event) | ||
{ | ||
if (isset($this->wire('input')->post->delete_permanently)) { | ||
$p = $event->arguments[0]; | ||
$session = $this->wire('session'); | ||
$afterDeleteRedirect = $this->wire('config')->urls->admin . "page/?open={$p->parent->id}"; | ||
if ($p->deleteable()) { | ||
$session->message(sprintf($this->strings->deleted, $p->url)); // Page deleted message | ||
$this->wire('pages')->delete($p, true); | ||
$session->redirect($afterDeleteRedirect); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
<?php | ||
|
||
namespace RockAdminTweaks; | ||
|
||
use ProcessWire\HookEvent; | ||
|
||
/** | ||
* If there is only 1 superuser with TfaWebAuthn set up on a debug mode site | ||
* and if the username is empty on login submission, we change the login_name | ||
* to the superuser's account name, and the login_pass to a dummy value to | ||
* allow the Session::authenticate hook to be called. | ||
* | ||
* Although the Session::authenticate method will fail we will hookAfter it | ||
* and pretend that it didn't. That will start 2FA credential collection | ||
* allowing us to proceed with just that protecting the account. | ||
* | ||
* For local installs where I have a YubiKey, this will be good enough. | ||
*/ | ||
|
||
final class QuickWebAuthnLogin extends Tweak | ||
{ | ||
private $supers; | ||
private $superuser; | ||
|
||
public function info(): array | ||
{ | ||
return [ | ||
'description' => 'Allow quick login as unique SuperUser, in debug mode, using just WebAuthn credentials', | ||
]; | ||
} | ||
|
||
|
||
public function ready(): void | ||
{ | ||
if ($this->wire->fields->get('tfa_type') === null) { | ||
return; // No 2FA set up | ||
} | ||
if (!$this->wire->config->debug) { | ||
return; // Not a debug mode site | ||
} | ||
|
||
$super_role_id = $this->wire->config->superUserRolePageID; | ||
$this->supers = $this->wire->users->find("roles=$super_role_id, tfa_type=TfaWebAuthn"); | ||
|
||
if (1 !== count($this->supers)) { | ||
return; // Not exactly 1 TfaWebAuthn superuser | ||
} | ||
|
||
$this->superuser = $this->supers->eq(0); | ||
|
||
if ('TfaWebAuthn' !== $this->superuser->hasTfa()) { | ||
return; // TfaWebAuthn Not fully configured for superuser | ||
} | ||
|
||
$this->wire->addHookAfter("ProcessLogin::loginFormProcessReady", $this, "fillLoginForm"); | ||
$this->wire->addHookAfter("Session::authenticate", $this, "overridePasswordAuthentication"); | ||
} | ||
|
||
|
||
protected function fillLoginForm(HookEvent $event) | ||
{ | ||
$uname = $this->wire->input->post->login_name ?? ''; | ||
$upass = $this->wire->input->post->login_pass ?? ''; | ||
if ('' === $uname && '' === $upass) { | ||
$this->wire->input->post->login_name = $this->superuser->name; | ||
$this->wire->input->post->login_pass = 'dummy_password'; // Not empty so PW to processes it | ||
} | ||
} | ||
|
||
|
||
protected function overridePasswordAuthentication(HookEvent $event) | ||
{ | ||
$user = $event->arguments(0); | ||
if ($user->id === $this->superuser->id && 'TfaWebAuthn' === $user->hasTfa()) { | ||
// Override earlier failed password authentication for this user | ||
// WebAuthn 2FA will kick in now, just as if the password was entered correctly. | ||
// So we only need to press our YubiKey button or use our face/fingerprint etc. | ||
$event->return = true; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
<?php | ||
|
||
namespace RockAdminTweaks; | ||
|
||
use ProcessWire\HookEvent; | ||
use ProcessWire\Inputfield; | ||
|
||
/** | ||
* Originally from AdminOnSteroids by RolandToth (tpr) | ||
*/ | ||
class CollapseInfo extends Tweak | ||
{ | ||
public function info(): array | ||
{ | ||
return [ | ||
'description' => 'Collapse Module Info section by default', | ||
]; | ||
} | ||
|
||
|
||
public function ready(): void | ||
{ | ||
$this->wire->addHookAfter('InputfieldMarkup::render', function (HookEvent $event) { | ||
$field = $event->object; | ||
if ($field->id === 'ModuleInfo') { | ||
$field->collapsed = Inputfield::collapsedYes; | ||
} | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
.aos-edit-prev, | ||
.aos-edit-next { | ||
padding: 0 0.3rem; | ||
position: relative; | ||
top: 1px; | ||
} | ||
|
||
.aos-edit-prev:not(:hover), | ||
.aos-edit-next:not(:hover) { | ||
color: #ccc; | ||
} | ||
|
||
.aos-edit-prev i, | ||
.aos-edit-next i { | ||
font-size: 17px !important; | ||
} | ||
|
||
html:not(.AdminThemeDefault) .aos-edit-prev i, | ||
html:not(.AdminThemeDefault) .aos-edit-next i { | ||
font-size: 27px !important; | ||
} | ||
|
||
.aos-edit-prev { | ||
margin-left: 0.6rem; | ||
} |
Oops, something went wrong.