Skip to content

Commit

Permalink
Merge branch '4.0' into 'main'
Browse files Browse the repository at this point in the history
  • Loading branch information
thorsten committed Jan 11, 2025
2 parents a51e5ec + 5a8710e commit fdba812
Show file tree
Hide file tree
Showing 15 changed files with 71 additions and 22 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ This is a log of major user-visible changes in each phpMyFAQ release.
- migrated from Webpack to Vite v6 (Thorsten)
- migrated from Jest to vitest (Thorsten)

### phpMyFAQ v4.0.5 - unreleased

- updated Hellenic translation (Vasileios Tzimourtos)
- fixed minor bugs (Thorsten)

### phpMyFAQ v4.0.4 - 2025-01-09

- improved update from v3 (Thorsten)
Expand Down
23 changes: 23 additions & 0 deletions docs/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -363,3 +363,26 @@ To create a new SSL certificate, you can use the following command:
$ mkcert -install -cert-file .docker/cert.pem -key-file .docker/cert-key.pem localhost

For more information, please visit the [mkcert](https://github.com/FiloSottile/mkcert) website.

### 6.7.2 Using a OpenLDAP docker container for testing

To test phpMyFAQ during development with an OpenLDAP docker container, you can use the following test setup:

$ docker pull rroemhild/test-openldap
$ docker run --rm -p 10389:10389 -p 10636:10636 rroemhild/test-openldap

The credentials for the OpenLDAP container are stored in the file content/core/config/ldap.php:

<?php
$PMF_LDAP['ldap_server'] = 'ldap://<your ip address>';
$PMF_LDAP['ldap_port'] = 10389;
$PMF_LDAP['ldap_user'] = 'cn=admin,dc=planetexpress,dc=com';
$PMF_LDAP['ldap_password'] = 'GoodNewsEveryone';
$PMF_LDAP['ldap_base'] = 'ou=people,dc=planetexpress,dc=com';

After activating the LDAP authentication in the admin backend, you can use the following credentials to log in:

Username: professor
Password: professor

More information about the OpenLDAP docker container can be found on the [Docker Hub](https://hub.docker.com/r/rroemhild/test-openldap).
2 changes: 1 addition & 1 deletion docs/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ download it and unzip the archive on your hard disk.

If you want to use Git, please run the following commands on your shell:

$ git clone git@github.com:thorsten/phpMyFAQ.git 3.2
$ git clone git@github.com:thorsten/phpMyFAQ.git 4.0
$ cd phpMyFAQ
$ curl -s https://getcomposer.org/installer | php
$ php composer.phar install
Expand Down
8 changes: 7 additions & 1 deletion phpmyfaq/src/phpMyFAQ/Auth/AuthLdap.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,14 @@ public function __construct(Configuration $configuration)
*/
public function create(string $login, #[SensitiveParameter] string $password, string $domain = ''): bool
{
$result = false;
$user = new User($this->configuration);
$result = $user->createUser($login, '', $domain);

try {
$result = $user->createUser($login, '', $domain);
} catch (\Exception $e) {
$this->configuration->getLogger()->info($e->getMessage());
}

$this->connect($this->activeServer);

Expand Down
3 changes: 1 addition & 2 deletions phpmyfaq/src/phpMyFAQ/Controller/AbstractController.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,7 @@ public function __construct()
* @param string[] $templateVars
* @param Response|null $response
* @return Response
* @throws Exception
* @throws LoaderError
* @throws Exception|LoaderError
*/
public function render(string $pathToTwigFile, array $templateVars = [], ?Response $response = null): Response
{
Expand Down
6 changes: 3 additions & 3 deletions phpmyfaq/src/phpMyFAQ/Controller/Api/SetupController.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\StreamedJsonResponse;
use Symfony\Component\HttpFoundation\StreamedResponse;

class SetupController extends AbstractController
{
Expand Down Expand Up @@ -108,7 +106,9 @@ public function updateDatabase(Request $request): JsonResponse
$this->configuration->set('main.maintenanceMode', 'false');
return new JsonResponse(['success' => '✅ Database successfully updated.'], Response::HTTP_OK);
}
} catch (Exception $exception) {

return new JsonResponse(['error' => 'Update database failed.'], Response::HTTP_BAD_GATEWAY);
} catch (Exception | \Exception $exception) {
return new JsonResponse(
['error' => 'Update database failed: ' . $exception->getMessage()],
Response::HTTP_BAD_GATEWAY
Expand Down
4 changes: 1 addition & 3 deletions phpmyfaq/src/phpMyFAQ/Controller/WebAuthnController.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
use phpMyFAQ\System;
use phpMyFAQ\Template\TwigWrapper;
use phpMyFAQ\Translation;
use phpMyFAQ\User\CurrentUser;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
Expand All @@ -41,7 +40,6 @@ public function __construct()
public function index(Request $request): Response
{
$system = new System();
$user = CurrentUser::getCurrentUser($this->configuration);

$topNavigation = [
[
Expand Down Expand Up @@ -98,7 +96,7 @@ public function index(Request $request): Response
'richSnippetsEnabled' => $this->configuration->get('seo.enableRichSnippets'),
'tplSetName' => TwigWrapper::getTemplateSetName(),
'msgLoginUser' => Translation::get('msgLoginUser'),
'isUserLoggedIn' => $user->isLoggedIn(),
'isUserLoggedIn' => $this->currentUser->isLoggedIn(),
'title' => Translation::get('msgLoginUser'),
'baseHref' => $system->getSystemUri($this->configuration),
'customCss' => $this->configuration->getCustomCss(),
Expand Down
2 changes: 2 additions & 0 deletions phpmyfaq/src/phpMyFAQ/Ldap.php
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ public function bind(string $rdn = '', #[SensitiveParameter] string $password =
if ('' === $rdn && '' === $password) {
return ldap_bind($this->ds);
}

return ldap_bind($this->ds, $rdn, $password);
}

Expand All @@ -163,6 +164,7 @@ public function getMail(string $username): bool|string
*/
private function getLdapData(string $username, string $data): bool|string
{

if ($this->ds === false) {
$this->error = 'The LDAP connection handler is not a valid resource.';

Expand Down
6 changes: 3 additions & 3 deletions phpmyfaq/src/phpMyFAQ/Mail.php
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ class Mail
public function __construct(Configuration $configuration)
{
// Set default value for public properties
$this->agent = $configuration->get('mail.remoteSMTP') ? 'SMTP' : 'built-in';
$this->agent = $configuration->get('mail.remoteSMTP') ? 'smtp' : 'built-in';
$this->boundary = self::createBoundary();
$this->messageId = '<' . Request::createFromGlobals()->server->get('REQUEST_TIME') . '.' . md5(microtime()) .
'@' . self::getServerName() . '>';
Expand Down Expand Up @@ -366,7 +366,7 @@ public function addTo(string $address, ?string $name = null): bool
*/
public function send(): int
{
// Sanity check
// Check
if (count($this->to) + count($this->cc) + count($this->bcc) < 1) {
throw new Exception(
'<strong>Mail Class</strong>: you need at least to set one recipient among TO, CC and BCC!'
Expand Down Expand Up @@ -430,7 +430,7 @@ public function send(): int
}

return match ($this->agent) {
'SMTP', 'built-in' => $mua->send($recipients, $this->headers, $this->body),
'smtp', 'built-in' => $mua->send($recipients, $this->headers, $this->body),
default => throw new Exception('<strong>Mail Class</strong>: ' . $this->agent . ' has no implementation!'),
};
}
Expand Down
9 changes: 3 additions & 6 deletions phpmyfaq/src/phpMyFAQ/News.php
Original file line number Diff line number Diff line change
Expand Up @@ -137,16 +137,15 @@ public function getLatestData(bool $showArchive = false, bool $active = true, bo
/**
* Fetches all news headers.
*
* @return array<mixed>
* @return array
*/
public function getHeader(): array
{
$headers = [];
$now = date('YmdHis');

$query = sprintf("
SELECT
id, datum, lang, header, active, date_start, date_end
id, datum, lang, header, active
FROM
%sfaqnews
WHERE
Expand All @@ -158,14 +157,12 @@ public function getHeader(): array

if ($this->configuration->getDb()->numRows($result) > 0) {
while ($row = $this->configuration->getDb()->fetchObject($result)) {
$expired = ($now > $row->date_end);
$headers[] = [
'id' => $row->id,
'lang' => $row->lang,
'header' => $row->header,
'date' => Date::createIsoDate($row->datum),
'active' => $row->active,
'expired' => $expired
'active' => $row->active
];
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,6 @@ public function getFilters(): array
private function getPermissionTranslation(string $string): string
{
$translationCode = sprintf('permission::%s', $string);
return Translation::get($translationCode);
return Translation::get($translationCode) ?? '';
}
}
1 change: 1 addition & 0 deletions phpmyfaq/src/phpMyFAQ/Translation.php
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,7 @@ protected function filename(string $language): string
private static function fetchTranslationFile(): array
{
$LANG_CONF = [];
include self::$translation->filename('en');
include self::$translation->filename(self::$translation->currentLanguage);

return $LANG_CONF;
Expand Down
2 changes: 1 addition & 1 deletion phpmyfaq/src/phpMyFAQ/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,7 @@ public function getUserByLogin(string $login, bool $raiseError = true): bool
$result = $this->configuration->getDb()->query($select);
if ($this->configuration->getDb()->numRows($result) !== 1) {
if ($raiseError) {
throw new Core\Exception(self::ERROR_USER_INCORRECT_LOGIN);
$this->errors[] = self::ERROR_USER_INCORRECT_LOGIN;
}

return false;
Expand Down
16 changes: 16 additions & 0 deletions phpmyfaq/src/phpMyFAQ/User/CurrentUser.php
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ public function login(string $login, string $password): bool
}

// Attempt to authenticate user by login and password
$this->authContainer = $this->sortAuthContainer($this->authContainer);
foreach ($this->authContainer as $authSource => $auth) {
if (!$this->checkAuth($auth)) {
continue; // Skip invalid Auth objects
Expand Down Expand Up @@ -758,4 +759,19 @@ protected function isFailedLastLoginAttempt(): bool
$result = $this->configuration->getDb()->query($select);
return $this->configuration->getDb()->numRows($result) !== 0;
}

protected function sortAuthContainer(array $authContainer): array
{
uksort($authContainer, function ($a, $b) {
if ($a === 'local') {
return 1;
}
if ($b === 'local') {
return -1;
}
return 0;
});

return $authContainer;
}
}
4 changes: 3 additions & 1 deletion phpmyfaq/src/phpMyFAQ/User/UserAuthentication.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ public function authenticate(string $username, #[SensitiveParameter] string $pas
$this->authenticateLdap();
$this->authenticateSso();

// Local
if ($this->currentUser->login($username, $password)) {
if ($this->currentUser->getUserData('twofactor_enabled')) {
$this->setTwoFactorAuth(true);
Expand All @@ -94,6 +93,9 @@ public function authenticate(string $username, #[SensitiveParameter] string $pas
return $this->currentUser;
}

/**
* @throws UserException
*/
private function authenticateLdap(): void
{
if ($this->configuration->isLdapActive() && function_exists('ldap_connect')) {
Expand Down

0 comments on commit fdba812

Please sign in to comment.