Skip to content

Commit

Permalink
Merge branch 'master' into drop-admin-user-config
Browse files Browse the repository at this point in the history
resolve conflict.
  • Loading branch information
ildyria committed Sep 5, 2022
2 parents cf19bc9 + b31d345 commit 43ec386
Show file tree
Hide file tree
Showing 54 changed files with 453 additions and 604 deletions.
25 changes: 7 additions & 18 deletions app/Actions/Install/ApplyMigration.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
use App\Exceptions\Internal\FrameworkException;
use Illuminate\Contracts\Container\BindingResolutionException;
use Illuminate\Support\Facades\Artisan;
use function Safe\unlink;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;

class ApplyMigration
{
Expand Down Expand Up @@ -73,26 +74,14 @@ public function keyGenerate(array &$output): void
try {
Artisan::call('key:generate', ['--force' => true]);
$this->str_to_array(Artisan::output(), $output);
if (!str_contains(end($output), 'Application key set successfully')) {
if (
!str_contains(end($output), 'Application key set successfully') ||
config('app.key') === null
) {
$output[] = 'We could not generate the encryption key.';
throw new InstallationFailedException('Could not generate encryption key');
}

// key is generated, we can safely remove that file (in theory)
$filename = base_path('.NO_SECURE_KEY');
if (file_exists($filename)) {
if (is_file($filename)) {
unlink($filename);
} else {
throw new InstallationFailedException('A filesystem object . ' . $filename . ' exists, but is not an ordinary file.');
}
}
} catch (\ErrorException $e) {
// possibly thrown by `unlink`
$output[] = $e->getMessage();
$output[] = 'Could not remove file `.NO_SECURE_KEY`.';
throw new InstallationFailedException('Could not remove file `.NO_SECURE_KEY`', $e);
} catch (BindingResolutionException $e) {
} catch (BindingResolutionException|NotFoundExceptionInterface|ContainerExceptionInterface $e) {
throw new FrameworkException('Laravel\'s container component', $e);
}
}
Expand Down
3 changes: 2 additions & 1 deletion app/Actions/Install/DefaultConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,15 @@ class DefaultConfig
*/
'permissions' => [
'.' => 'file_exists|is_readable|is_writable|is_executable',
'database/' => 'file_exists|is_readable|is_writable|is_executable',
'database/database.sqlite' => 'file_exists|is_readable|is_writable',
'storage/framework/' => 'file_exists|is_readable|is_writable|is_executable',
'storage/framework/views/' => 'file_exists|is_readable|is_writable|is_executable',
'storage/framework/cache/' => 'file_exists|is_readable|is_writable|is_executable',
'storage/framework/sessions/' => 'file_exists|is_readable|is_writable|is_executable',
'storage/logs/' => 'file_exists|is_readable|is_writable|is_executable',
'bootstrap/cache/' => 'file_exists|is_readable|is_writable|is_executable',
'public/dist/' => 'file_exists|is_readable|is_writable|is_executable',
'public/img/' => 'file_exists|is_readable|is_writable|is_executable',
'public/sym/' => 'file_exists|is_readable|is_writable|is_executable',
'public/uploads/' => 'file_exists|is_readable|is_writable|is_executable',
],
Expand Down
2 changes: 2 additions & 0 deletions app/Actions/Settings/SetLogin.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ public function do(string $username, string $password): User
$adminUser = User::query()->findOrFail(0);
$adminUser->username = $username;
$adminUser->password = Hash::make($password);
$adminUser->is_locked = false;
$adminUser->may_upload = true;
$adminUser->save();

return $adminUser;
Expand Down
2 changes: 2 additions & 0 deletions app/Actions/User/ResetAdmin.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ public function do(): void
$user->id = 0;
$user->username = '';
$user->password = '';
$user->is_locked = false;
$user->may_upload = true;
$user->save();
}
}
13 changes: 7 additions & 6 deletions app/Console/Commands/FixPermissions.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,14 @@

use App\Actions\Diagnostics\Checks\BasicPermissionCheck;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Storage;
use function Safe\chmod;
use function Safe\fileowner;
use function Safe\sprintf;
use Symfony\Component\Console\Exception\InvalidArgumentException;

class FixPermissions extends Command
{
public const DIRECTORIES = [
'public/uploads',
'public/sym',
];

/**
* The name and signature of the console command.
*
Expand Down Expand Up @@ -52,6 +48,11 @@ class FixPermissions extends Command
*/
public function handle(): int
{
$directories = [
Storage::disk('images')->path(''),
Storage::disk('symbolic')->path(''),
];

if (!extension_loaded('posix')) {
$this->error('Non-POSIX OS detected: Command unsupported');

Expand All @@ -63,7 +64,7 @@ public function handle(): int
clearstatcache(true);
$this->effUserId = posix_geteuid();

foreach (self::DIRECTORIES as $directory) {
foreach ($directories as $directory) {
$this->line(sprintf('Scanning: <info>%s</info>', $directory));
$this->fixPermissionsRecursively($directory);
}
Expand Down
98 changes: 97 additions & 1 deletion app/Exceptions/Handler.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,60 @@
use App\Exceptions\Handlers\NoEncryptionKey;
use App\Models\Logs;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Contracts\Container\BindingResolutionException;
use Illuminate\Contracts\Container\Container;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Illuminate\Http\Request;
use Illuminate\Session\TokenMismatchException;
use Illuminate\Support\Arr;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use Symfony\Component\HttpFoundation\Response as SymfonyResponse;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;

/**
* Lychee's custom exception handler.
*
* While the overall architectural approach of the original exception handler
* of the framework is fine, the original exception handler is mostly broken
* when it comes to the details.
*
* The overall architectural approach is as follows:
*
* 1. Substitute or wrap certain exceptions by or into other exceptions
* (i.e. via `mapException`)
* 2. Decide whether the client expects an HTML or JSON response
* 3. Convert (or "render") the exception into a response with said content
* type
*
* However, there are two major issues with the original exception handler:
*
* - Substitution of exception is not limited to `mapException` but happens
* all the time which makes it hard to reliably predict what happens to
* an exception when a method (other than `mapException`) is called.
* One might end up with a different exception.
* Moreover, not all of these substitution are sensible enough to add the
* original exception as a predecessor to the new exception.
* - A constant mix-up of the terms "HTTP" and "HTML".
* The framework frequently uses the term "HTTP" as an antonym to "JSON"
* when "HTML" would be rather appropriate.
* For example like in `renderJsonResponse($e)` vs. `renderHttpResponse($e)`.
* The latter is called, when an exception shall be converted into HTML.
* But of course, a JSON response is also an HTTP response.
* It seems as if the framework is not even aware of this confusion.
*
* 90% of this handler are bug fixes.
* This means, parent methods are not overwritten, because we need a special
* non-standard behaviour, but simply the _right_ behaviour.
* Unfortunately, this class cannot solve the unfortunate naming of some
* methods, but must stick to the names used by the parent class.
* Alternatively, this class could overwrite the entry method `render($e)`,
* re-implement everything which comes after that (even using better names)
* and let the rest of the parent class go down the drain.
* However, this bears the risk that some 3rd-party calls unfixed methods of
* the original exception handler.
*/
class Handler extends ExceptionHandler
{
/**
Expand Down Expand Up @@ -153,12 +200,61 @@ protected function mapException(\Throwable $e): \Throwable
}

/**
* Renders the given HttpException.
* Prepare a response for the given exception.
*
* This method is called by the framework, _after_ the framework has
* decided that the client expects a HTML response, but _before_ the
* actual work horse {@link Handler::renderHttpException} is called.
*
* This method is 99% identical to the parent method except for a tiny
* bug fix which adds the original exception to the encapsulating
* `HttpException`.
*
* @param Request $request
* @param \Throwable $e
*
* @return SymfonyResponse
*
* @throws BindingResolutionException
* @throws \InvalidArgumentException
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
protected function prepareResponse($request, \Throwable $e): SymfonyResponse
{
if (!$this->isHttpException($e) && config('app.debug') === true) {
return $this->toIlluminateResponse($this->convertExceptionToResponse($e), $e);
}

if (!$this->isHttpException($e)) {
$e = new HttpException(500, $e->getMessage(), $e);
}

// `renderHttpException` expects `$e` to be an instance of
// `HttpExceptionInterface`.
// This is ensured by `isHttpException` above, but PHPStan does not
// understand that.
// @phpstan-ignore-next-line
return $this->toIlluminateResponse($this->renderHttpException($e), $e);
}

/**
* Renders the given HttpException into HTML.
*
* This method is called by the framework if
* 1. `config('app.debug')` is not set, i.e. the application is not in debug mode
* 2. the client expects an HTML response
*
* **Attention:**
* This method is a misnomer caused by the framework.
* The framework provides two methods `renderHttpException` and
* `renderJsonException` with the former being called if the client
* expects HTML.
* Hence, the method should rather be named `renderHtmlException`.
* That current name of the method, if meant as an antonym to
* `renderJsonException` is obviously nonsense as JSON is also transported
* over HTTP.
*
* @param HttpExceptionInterface $e
*
* @return SymfonyResponse
Expand Down
2 changes: 0 additions & 2 deletions app/Exceptions/Handlers/NoEncryptionKey.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
use App\Contracts\HttpExceptionHandler;
use App\Redirections\ToInstall;
use Illuminate\Encryption\MissingAppKeyException;
use function Safe\touch;
use Symfony\Component\HttpFoundation\Response as SymfonyResponse;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface as HttpException;
use Throwable;
Expand Down Expand Up @@ -37,7 +36,6 @@ public function check(HttpException $e): bool
public function renderHttpException(SymfonyResponse $defaultResponse, HttpException $e): SymfonyResponse
{
try {
touch(base_path('.NO_SECURE_KEY'));
$redirectResponse = ToInstall::go();
$contentType = $defaultResponse->headers->get('Content-Type');
if ($contentType !== null && $contentType !== '') {
Expand Down
16 changes: 10 additions & 6 deletions app/Http/Controllers/Administration/SettingsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use App\Http\Requests\Settings\ChangeLoginRequest;
use App\Http\Requests\Settings\SetSortingRequest;
use App\Models\Configs;
use App\Models\User;
use App\Rules\LicenseRule;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\ModelNotFoundException;
Expand All @@ -27,17 +28,17 @@ class SettingsController extends Controller
{
/**
* Set the Login information for the admin user (id = 0)
* when the later is not initialized.
* when the latter is not initialized.
*
* @param SetAdminLoginRequest $request
* @param SetLogin $setLogin
*
* @return void
* @return User
*
* @throws LycheeException
* @throws ModelNotFoundException
*/
public function setLogin(SetAdminLoginRequest $request, SetLogin $setLogin): void
public function setLogin(SetAdminLoginRequest $request, SetLogin $setLogin): User
{
$adminUser = $setLogin->do(
$request->username(),
Expand All @@ -47,6 +48,8 @@ public function setLogin(SetAdminLoginRequest $request, SetLogin $setLogin): voi
// Otherwise, the session is out-of-sync and falsely assumes the user
// to be unauthenticated upon the next request.
Auth::login($adminUser);

return $adminUser;
}

/**
Expand All @@ -55,12 +58,11 @@ public function setLogin(SetAdminLoginRequest $request, SetLogin $setLogin): voi
* @param ChangeLoginRequest $request
* @param UpdateLogin $updateLogin
*
* @return void
* @return User
*
* @throws LycheeException
* @throws ModelNotFoundException
*/
public function updateLogin(ChangeLoginRequest $request, UpdateLogin $updateLogin): void
public function updateLogin(ChangeLoginRequest $request, UpdateLogin $updateLogin): User
{
$currentUser = $updateLogin->do(
$request->username(),
Expand All @@ -72,6 +74,8 @@ public function updateLogin(ChangeLoginRequest $request, UpdateLogin $updateLogi
// Otherwise, the session is out-of-sync and falsely assumes the user
// to be unauthenticated upon the next request.
Auth::login($currentUser);

return $currentUser;
}

/**
Expand Down
12 changes: 0 additions & 12 deletions app/Http/Controllers/IndexController.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
namespace App\Http\Controllers;

use App\Exceptions\ModelDBException;
use App\Facades\Lang;
use App\ModelFunctions\ConfigFunctions;
use App\ModelFunctions\SymLinkFunctions;
use App\Models\Configs;
Expand Down Expand Up @@ -40,13 +39,8 @@ public function __construct(ConfigFunctions $configFunctions, SymLinkFunctions $
public function show(): View
{
if (Configs::getValueAsBool('landing_page_enable')) {
$lang = Lang::get_lang();
$lang['language'] = Configs::getValueAsString('lang');

$infos = $this->configFunctions->get_pages_infos();

$menus = Page::menu()->get();

$title = Configs::getValueAsString('site_title');
$rss_enable = Configs::getValueAsBool('rss_enable');

Expand All @@ -55,10 +49,8 @@ public function show(): View
$page_config['display_socials'] = false;

return view('landing', [
'locale' => $lang,
'title' => $title,
'infos' => $infos,
'menus' => $menus,
'page_config' => $page_config,
'rss_enable' => $rss_enable,
]);
Expand Down Expand Up @@ -94,17 +86,13 @@ public function gallery(): View
$this->symLinkFunctions->remove_outdated();
$infos = $this->configFunctions->get_pages_infos();

$lang = Lang::get_lang();
$lang['language'] = Configs::getValueAsString('lang');

$title = Configs::getValueAsString('site_title');
$rss_enable = Configs::getValueAsBool('rss_enable');
$page_config = [];
$page_config['show_hosted_by'] = true;
$page_config['display_socials'] = Configs::getValueAsBool('display_social_in_gallery');

return view('gallery', [
'locale' => $lang,
'title' => $title,
'infos' => $infos,
'page_config' => $page_config,
Expand Down
Loading

0 comments on commit 43ec386

Please sign in to comment.