Update Kirby and add password guard

This commit is contained in:
isUnknown 2026-02-09 17:05:41 +01:00
parent aaf1aa7890
commit 55d4e45891
987 changed files with 160116 additions and 66454 deletions

View file

@ -0,0 +1,20 @@
# This file is for unifying the coding style for different editors and IDEs
# editorconfig.org
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[*.php]
indent_size = 4
[*.md,*.txt]
trim_trailing_whitespace = false
insert_final_newline = false
[composer.json]
indent_size = 4

View file

@ -0,0 +1,11 @@
# Note: You need to uncomment the lines you want to use; the other lines can be deleted
# Git
# .gitattributes export-ignore
# .gitignore export-ignore
# Tests
# /.coveralls.yml export-ignore
# /.travis.yml export-ignore
# /phpunit.xml.dist export-ignore
# /tests/ export-ignore

View file

@ -0,0 +1,8 @@
# OS files
.DS_Store
# npm modules
/node_modules
# Composer files
/vendor

View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) <Year> <Your Name>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -0,0 +1,90 @@
# Kirby Password Guard
**Kirby Password Guard** is a simple password protection for your [Kirby](https://getkirby.com/) website. It allows you
to
set a password that needs to be entered in order to access the site. This can be useful for staging sites to prevent
unwanted access. Logged in users can access the site normally but any guest will run into the password entry page.
![kirby-password-guard](https://github.com/user-attachments/assets/2e4596a7-56a9-4084-8b5c-4c3358e4f34c)
****
## Installation
### Download
Download and copy this repository to `/site/plugins/kirby-password-guard`.
### Git submodule
```
git submodule add https://github.com/pechente/kirby-password-guard.git site/plugins/kirby-password-guard
```
### Composer
```
composer require pechente/kirby-password-guard
```
## Setup
### Configuration
Add the following lines to your config.php:
```php
return [
'pechente.kirby-password-guard' => [
'enabled' => true, // Optional - default is true
'password' => 'password', // Required - The password used to access the site. If left empty the plugin will not be enabled.
'pattern' => '(:all)', // Optional - The pattern to protect. By default, all pages are protected. Check the Kirby documentation for more information.
]
];
```
### Template
You can overwrite the template for the password form by creating the file `site/templates/password-guard.php`. Here's a
minimal example of what this file needs to include:
```php
<!DOCTYPE html>
<html>
<head>
<title><?= $page->title() ?></title>
</head>
<body>
<form method="post" action="<?= $page->url() ?>">
<label for="password">Password:</label>
<input type="password" name="password" id="password" required>
<input type="hidden" name="redirect" value="<?= $page->redirect() ?>">
<button type="submit">Submit</button>
<?php if ($page->passwordIncorrect()->toBool()): ?>
<div class="info">Wrong Password</div>
<?php endif ?>
</form>
</body>
</html>
```
Please keep in mind that you should avoid adding code from your website like the stylesheets or header / footer since it
might defeat the purpose of the password protection.
## FAQ & Troubleshooting
### I'm not seeing the password prompt when I visit my site
Make sure you're not signed in. If you're signed in, you won't see the password prompt. I'd recommend testing the plugin
in a private browsing window.
If that didn't work, make sure that the configuration is correct.
### How secure is the password protection?
The password is verified on the backend and cannot easily be circumvented. The password is only ever stored as a hash on
the user's side.
---
If you have any issues with the plugin, please open an issue here on GitHub.

View file

@ -0,0 +1,18 @@
# Security Policy
## Supported Versions
*Use this section to tell people about which versions of your project are currently being supported with security updates.*
| Version | Supported |
| ------- | ------------------ |
| 5.1.x | :white_check_mark: |
| 5.0.x | :x: |
| 4.0.x | :white_check_mark: |
| < 4.0 | :x: |
## Reporting a Vulnerability
*Use this section to tell people how to report a vulnerability.*
*Tell them where to go, how often they can expect to get an update on a reported vulnerability, what to expect if the vulnerability is accepted or declined, etc.*

View file

@ -0,0 +1,35 @@
{
"name": "pechente/kirby-password-guard",
"description": "Kirby Password Guard",
"license": "MIT",
"type": "kirby-plugin",
"homepage": "https://github.com/Pechente/kirby-password-guard/",
"version": "1.3.0",
"authors": [
{
"name": "René Henrich",
"email": "contact@rene-henrich.de"
}
],
"require": {
"php": ">=8.0.0",
"getkirby/cms": ">=4.0.0",
"getkirby/composer-installer": "^1.2"
},
"keywords": [
"kirby5",
"kirby5-cms",
"kirby5-plugin",
"password",
"guard",
"protect",
"development",
"panel"
],
"config": {
"optimize-autoloader": true,
"allow-plugins": {
"getkirby/composer-installer": true
}
}
}

View file

@ -0,0 +1,73 @@
<?php
use Kirby\Cms\Page;
Kirby::plugin('pechente/kirby-password-guard', [
'templates' => [
'password-guard' => __DIR__ . '/templates/password-guard.php',
],
'snippets' => [
'panel-icon' => __DIR__ . '/snippets/panel-icon.php',
],
'routes' => [
[
'pattern' => 'password-guard',
'language' => '*',
'method' => 'POST',
'action' => function () {
$password = get('password');
$hashedPassword = password_hash($password, PASSWORD_BCRYPT);
$session = kirby()->session();
$session->set('kirby-password-guard.password-hash', $hashedPassword);
$redirect = get('redirect');
kirby()->response()->redirect($redirect);
}
],
[
'pattern' => option('pechente.kirby-password-guard.pattern', '(:all)'),
'method' => 'GET',
'action' => function (string $uid) {
$query = get();
$redirectUrl = $uid . (empty($query) ? '' : '?' . http_build_query($query));
if (
option('pechente.kirby-password-guard.enabled') === false ||
!option('pechente.kirby-password-guard.password') ||
kirby()->user()
) {
$this->next();
}
$passwordIncorrect = false;
// check session for password
$session = kirby()->session();
$hash = $session->get('kirby-password-guard.password-hash');
$password = option('pechente.kirby-password-guard.password');
// Display the page if the password is correct
if ($hash) {
if (password_verify($password, $hash)) {
$this->next();
} else {
$passwordIncorrect = true;
kirby()->session()->remove('kirby-password-guard.password-hash');
}
}
// Render the Password Entry Page if it's not correct
$passwordPage = new Page([
'slug' => 'password-guard',
'template' => 'password-guard',
'content' => [
'title' => 'Password Guard',
'redirect' => url($redirectUrl),
'passwordIncorrect' => $passwordIncorrect
]
]);
return $passwordPage->render();
}
]
],
]);

View file

@ -0,0 +1,15 @@
<?php
$name ??= null;
$panelIcons = svg($kirby->root('kirby') . '/panel/dist/img/icons.svg');
if ($panelIcons && $name) {
if (preg_match('/<symbol[^>]*id="icon-' . $name . '"[^>]*viewBox="(.*?)"[^>]*>(.*?)<\/symbol>/s', $panelIcons, $matches)) {
if (preg_match('/<use href="#icon-(.*?)"[^>]*?>/s', $matches[2], $use)) {
return icon($use[1]);
}
echo '<svg class="k-icon" data-type="' . $name . '" xmlns="http://www.w3.org/2000/svg" viewBox="' . $matches[1] . '">' . $matches[2] . '</svg>';
}
}

View file

@ -0,0 +1,69 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title><?= $page->title() ?></title>
<style><?php F::load($kirby->root('kirby') . '/panel/dist/css/style.min.css'); ?></style>
</head>
<body>
<div class="k-panel k-panel-outside">
<div class="k-dialog k-login k-login-dialog">
<?php if($page->passwordIncorrect()->toBool()): ?>
<div data-theme="error" class="k-notification k-login-alert">
<p><?= t('error.user.password.wrong') ?></p>
<button type="button" class="k-button k-login-alert-close">
<span class="k-button-icon">
<?= snippet('panel-icon', ['name' => 'cancel']) ?>
</span>
</button>
</div>
<?php endif ?>
<div class="k-dialog-body">
<form class="k-login-form" method="post" action="<?= $page->url() ?>">
<div class="k-login-fields">
<header class="k-field-header">
<label class="k-label" title="<?= t('password') ?>">
<span class="k-label-text"><?= t('password') ?></span>
</label>
</header>
<div class="k-input">
<span class="k-input-element">
<input type="password" name="password" id="password" class="k-text-input" autofocus required>
<input type="hidden" name="redirect" value="<?= $page->redirect() ?>">
</span>
<span class="k-input-icon">
<?= snippet('panel-icon', ['name' => 'key']) ?>
</span>
</div>
</div>
<div class="k-login-buttons">
<button data-has-text="true" data-size="lg" data-theme="positive" data-variant="filled" type="submit" class="k-button k-login-button" style="width: 100%">
<span class="k-button-icon">
<?= snippet('panel-icon', ['name' => 'unlock']) ?>
</span>
<span class="k-button-text"><?= t('lock.unlock') ?></span>
</button>
</div>
</form>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function () {
// Cancel button to remove error alert
const icon = document.querySelector('.k-login-alert-close');
const alert = document.querySelector('.k-login-alert');
icon?.addEventListener('click', () => alert?.remove());
// Password label to focus on input
const label = document.querySelector('.k-label');
const input = document.querySelector('.k-text-input');
label?.addEventListener('click', () => input?.focus());
});
</script>
</body>
</html>