Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
BernhardBaumrock committed May 15, 2024
2 parents 3e22213 + 4593d76 commit c1831e0
Show file tree
Hide file tree
Showing 10 changed files with 572 additions and 2 deletions.
4 changes: 2 additions & 2 deletions classes/Tweak.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ public function ready(): void

public final function loadCSS(): void
{
$jsfile = substr($this->file, 0, -3) . "css";
$url = wire()->config->versionUrl($this->pathToUrl($jsfile));
$cssfile = substr($this->file, 0, -3) . "css";
$url = wire()->config->versionUrl($this->pathToUrl($cssfile));
wire()->config->styles->add($url);
}

Expand Down
3 changes: 3 additions & 0 deletions tweaks/General/BypassTrash.css
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;
}
55 changes: 55 additions & 0 deletions tweaks/General/BypassTrash.js
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;
});
179 changes: 179 additions & 0 deletions tweaks/General/BypassTrash.php
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);
}
}
}
}
81 changes: 81 additions & 0 deletions tweaks/General/QuickWebAuthnLogin.php
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;
}
}
}
30 changes: 30 additions & 0 deletions tweaks/Modules/CollapseInfo.php
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;
}
});
}
}
25 changes: 25 additions & 0 deletions tweaks/PageEdit/PrevNextPage.css
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;
}
Loading

0 comments on commit c1831e0

Please sign in to comment.