Skip to content

Commit

Permalink
Merge branch 'hotfix/0.15.2'
Browse files Browse the repository at this point in the history
  • Loading branch information
dshoreman committed Dec 30, 2022
2 parents 605abb3 + ef0007c commit 6c64084
Show file tree
Hide file tree
Showing 45 changed files with 15,480 additions and 5,280 deletions.
1 change: 1 addition & 0 deletions .github/scripts/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ set_test_skel_permissions() {
sudo chown -Rv root:root "${skeleton}/protected"

sudo chmod -v 777 "${skeleton}"
sudo chmod -v 666 "${skeleton}"/clearable.txt
sudo chmod -v 775 "${skeleton}"/mixed/another-dir
sudo chmod -v 664 "${skeleton}"/mixed/hello.md "${skeleton}"/hidden/.bar
sudo chmod -v 600 "${skeleton}/protected/forbidden"
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ jobs:
- name: Run PHP mess detection tool
run: make phpmd PHPMD_FORMAT="github"
- name: Check for magic numbers
run: make phpmnd MND_ARGS="--non-zero-exit-on-violation"
run: make phpmnd
- name: Gather PHP insights
if: ${{ '8.0-ubuntu-20.04' == format('{0}-{1}', matrix.php, matrix.os) }}
run: make insights INSIGHT_ARGS="--ansi --format=github-action --disable-security-check"
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
/.vscode
/.vagrant
/node_modules
/notes
/public/mix-manifest.json
/public/css/app.css
/public/css/theme.*.css
Expand Down
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]


## [0.15.2] - 2022-12-30
### Added
* [installer] Pusher app credentials can now be set with `--pusher id:key:secret[:cluster]`


## [0.15.1] - 2022-12-27
### Fixed
* [auth] Added port to `APP_URL` when used as stateful domain to fix CSRF Token Mismatch
Expand Down Expand Up @@ -277,7 +282,8 @@ This is the first version with a "true" GitHub Release. For older releases, chec
* Basic login/logout auth stuff


[Unreleased]: https://github.com/dshoreman/servidor/compare/v0.15.1...develop
[Unreleased]: https://github.com/dshoreman/servidor/compare/v0.15.2...develop
[0.15.2]: https://github.com/dshoreman/servidor/compare/v0.15.1...v0.15.2
[0.15.1]: https://github.com/dshoreman/servidor/compare/v0.15.0...v0.15.1
[0.15.0]: https://github.com/dshoreman/servidor/compare/v0.14.0...v0.15.0
[0.14.0]: https://github.com/dshoreman/servidor/compare/v0.13.0...v0.14.0
Expand Down
5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ test-8.1:
@vagrant ssh -c "cd /var/servidor && sudo -u www-data phpdbg8.1 -qrr vendor/bin/phpunit -c build/phpunit/config.xml $(test)"

test-for-ci:
vendor/bin/phpunit -c build/phpunit/config.xml --coverage-clover=coverage.xml --exclude-group "broken-travis"
vendor/bin/phpunit -c build/phpunit/config.xml --coverage-clover=coverage.xml

coverage:
@vagrant ssh -c "cd /var/servidor && sudo -u www-data php8.0 vendor/bin/phpunit -c build/phpunit/config.xml --coverage-text"
Expand Down Expand Up @@ -143,6 +143,9 @@ psalm:
phpcsf:
vendor/bin/php-cs-fixer fix $(PHP_CSF_ARGS) --config build/php-cs-fixer/config.php

phpcsfix:
vendor/bin/php-cs-fixer fix $(CS_ARGS) --config build/php-cs-fixer/config.php

phpcs:
vendor/bin/phpcs app -p --standard=PSR12

Expand Down
4 changes: 4 additions & 0 deletions app/Databases/DatabaseDTO.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ public function __construct(mixed ...$args)
{
$this->tables = new TableCollection();

if (!isset($args['tables'])) {
$args['tables'] = $this->tables;
}

parent::__construct($args);
}

Expand Down
11 changes: 5 additions & 6 deletions app/Databases/DatabaseManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
use Doctrine\DBAL\DriverManager;
use Doctrine\DBAL\Exception\DriverException;
use Doctrine\DBAL\Schema\AbstractSchemaManager;
use Doctrine\DBAL\Schema\MySQLSchemaManager;
use Illuminate\Contracts\Config\Repository;

class DatabaseManager
Expand All @@ -22,18 +21,18 @@ public function __construct(
?Connection $connection = null,
?AbstractSchemaManager $manager = null,
) {
/** @var array{user: string, password: string} $dbalConfig */
$dbalConfig = $config->get('database.dbal');
$socket = (string) $config->get('database.connections.mysql.unix_socket');

/** @psalm-suppress InvalidArgument */
$this->connection = $connection ?? DriverManager::getConnection(
array_merge((array) $config->get('database.dbal'), [
array_merge($dbalConfig, [
'driver' => 'pdo_mysql',
'unix_socket' => $socket,
]),
);
$this->manager = $manager ?: new MySQLSchemaManager(
$this->connection,
$this->connection->getDatabasePlatform(),
);
$this->manager = $manager ?: $this->connection->createSchemaManager();
}

public function create(DatabaseDTO $database): DatabaseDTO
Expand Down
72 changes: 41 additions & 31 deletions app/FileManager/FileManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -158,23 +158,20 @@ private function loadPermissions(string $path, string $name = '.* *'): array

[$filename, $text, $octal] = explode(' ', $file);

if (self::DECIMAL_PERMISSION_LENGTH === mb_strlen($octal)) {
$octal = '0' . $octal;
}

$perms[$filename] = compact('text', 'octal');
}

return $this->filePerms = $perms;
}

/**
* TODO: See if the ErrorControlOperator still needs
* to be suppressed once phpmd is working on PHP 8.x.
*
* @param SplFileInfo|string $file
*
* @SuppressWarnings(PHPMD.ErrorControlOperator)
*
* @return array{0: SplFileInfo, 1: array}
*/
private function loadFile($file): array
private function loadFile(SplFileInfo|string $file): array
{
if (\is_string($file)) {
$path = explode('/', $file);
Expand All @@ -183,28 +180,28 @@ private function loadFile($file): array
$file = new SplFileInfo($file, implode('/', $path), $name);
}

$owner = posix_getpwuid($file->getOwner()) ?: [];
$group = posix_getgrgid($file->getGroup()) ?: [];
return [$file, $this->makeFileData($file)];
}

$data = [
'filename' => $file->getFilename(),
/**
* @SuppressWarnings(PHPMD.ErrorControlOperator)
*/
private function makeFileData(SplFileInfo $file): array
{
$filename = $file->getFilename();

return [
'filename' => $filename,
'filepath' => $file->getPath(),
'mimetype' => @mime_content_type((string) $file->getRealPath()),
'isDir' => $file->isDir(),
'isFile' => $file->isFile(),
'isLink' => $file->isLink(),
'target' => $file->isLink() ? $file->getLinkTarget() : '',
'owner' => $owner['name'] ?? '???',
'group' => $group['name'] ?? '???',
'owner' => (posix_getpwuid($file->getOwner()) ?: [])['name'] ?? '???',
'group' => (posix_getgrgid($file->getGroup()) ?: [])['name'] ?? '???',
'perms' => $this->filePerms[$filename],
];

$data['perms'] = $this->filePerms[$data['filename']];

if (self::DECIMAL_PERMISSION_LENGTH === mb_strlen($data['perms']['octal'])) {
$data['perms']['octal'] = '0' . $data['perms']['octal'];
}

return [$file, $data];
}

/** @param SplFileInfo|string $file */
Expand All @@ -219,21 +216,34 @@ private function fileWithContents(string $file): array
{
[$file, $data] = $this->loadFile($file);

if ($data['mimetype'] && 'text/' !== mb_substr((string) $data['mimetype'], 0, 5)) {
throw new UnsupportedFileType('Unsupported filetype');
if (
$data['mimetype']
&& 'application/x-empty' !== $data['mimetype']
&& 'text/' !== mb_substr((string) $data['mimetype'], 0, 5)
) {
throw new UnsupportedFileType("Unsupported filetype {$data['mimetype']}");
}

try {
$data['contents'] = $file->getContents();
} catch (RuntimeException $e) {
$msg = $e->getMessage();
$data['contents'] = '';
$data['error'] = ['code' => 418, 'msg' => $msg];
$deniedError = 'failed to open stream: permission denied';
$data = $this->addErrorFromException($e, $data);
}

if (Str::contains(mb_strtolower($msg), $deniedError)) {
$data['error'] = ['code' => 403, 'msg' => 'Permission denied'];
}
return $data;
}

private function addErrorFromException(RuntimeException $e, array $data): array
{
$msg = $e->getMessage();

$data = array_merge($data, [
'error' => ['code' => 418, 'msg' => $msg],
'contents' => '',
]);

if (Str::contains(mb_strtolower($msg), 'failed to open stream: permission denied')) {
$data['error'] = ['code' => 403, 'msg' => 'Permission denied'];
}

return $data;
Expand Down
41 changes: 19 additions & 22 deletions app/Http/Controllers/Files/EditFile.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,42 +3,39 @@
namespace Servidor\Http\Controllers\Files;

use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Validation\ValidationException;
use Servidor\FileManager\PathNotFound;
use Servidor\Http\Requests\FileManager\EditFile as EditFileRequest;

class EditFile extends Controller
{
public function __invoke(Request $request): JsonResponse
public function __invoke(EditFileRequest $request): JsonResponse
{
$filepath = $request->query('file');

if (!$filepath || !\is_string($filepath)) {
throw ValidationException::withMessages(['file' => 'File path must be specified.']);
}

$data = $request->validate([
'file' => 'required',
'contents' => 'required|nullable',
]);

try {
$file = $this->fm->open($filepath);
$data = $request->validated();
$file = $this->fm->open($data['file']);
} catch (PathNotFound $e) {
$status = Response::HTTP_NOT_FOUND;

return response()->json([
'error' => ['code' => $status, 'msg' => $e->getMessage()],
], $status);
return $this->jsonError($e);
}

if ($file['contents'] === $data['contents']) {
return response()->json('', Response::HTTP_NOT_MODIFIED);
}

$this->fm->save($filepath, (string) $data['contents']);
$this->fm->save($data['file'], $data['contents']);

return response()->json($this->fm->open($data['file']));
}

return response()->json($this->fm->open($filepath));
private function jsonError(PathNotFound $e): JsonResponse
{
$status = Response::HTTP_NOT_FOUND;

return response()->json([
'error' => [
'code' => $status,
'msg' => $e->getMessage(),
],
], $status);
}
}
41 changes: 23 additions & 18 deletions app/Http/Controllers/System/UsersController.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,26 +23,9 @@ public function index(): JsonResponse
public function store(CreateUser $request): JsonResponse
{
$data = $request->validated();
$createGroup = (bool) $request->input('user_group', false);

try {
$user = new LinuxUser(['name' => $data['name']]);

$user->setCreateHome((bool) $request->input('create_home', false))
->setHomeDirectory((string) ($data['dir'] ?? ''))
->setShell((string) ($data['shell'] ?? ''))
->setSystem((bool) ($data['system'] ?? false))
->setUid(isset($data['uid']) ? (int) $data['uid'] : null)
;

$gid = isset($data['gid']) ? (int) $data['gid'] : null;
if (!$createGroup && $gid) {
$user->setGid($gid);
}

$user->setUserGroup($createGroup);

$user = SystemUser::createCustom($user);
$user = $this->createUser($request, $data);
} catch (GenericUserSaveFailure $e) {
$data['error'] = $e->getMessage();

Expand All @@ -52,6 +35,28 @@ public function store(CreateUser $request): JsonResponse
return response()->json($user, Response::HTTP_CREATED);
}

private function createUser(CreateUser $request, array $data): array
{
$user = new LinuxUser(['name' => $data['name']]);
$createGroup = (bool) $request->input('user_group', false);

$user->setCreateHome((bool) $request->input('create_home', false))
->setHomeDirectory((string) ($data['dir'] ?? ''))
->setShell((string) ($data['shell'] ?? ''))
->setSystem((bool) ($data['system'] ?? false))
->setUid(isset($data['uid']) ? (int) $data['uid'] : null)
;

$gid = isset($data['gid']) ? (int) $data['gid'] : null;
if (!$createGroup && $gid) {
$user->setGid($gid);
}

$user->setUserGroup($createGroup);

return SystemUser::createCustom($user);
}

public function update(UpdateUser $request, int $uid): JsonResponse
{
try {
Expand Down
3 changes: 2 additions & 1 deletion app/Http/Requests/Databases/NewDatabase.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ public function rules(): array
*/
public function validated(): array
{
/** @var array{database: string} $data */
$data = parent::validated();

return array_merge($data, ['database' => (string) $data['database']]);
return array_merge($data, ['database' => $data['database']]);
}
}
36 changes: 36 additions & 0 deletions app/Http/Requests/FileManager/EditFile.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

namespace Servidor\Http\Requests\FileManager;

use Illuminate\Foundation\Http\FormRequest;

class EditFile extends FormRequest
{
public function rules(): array
{
return [
'file' => 'required',
'contents' => 'present',
];
}

public function messages(): array
{
return [
'file.required' => 'File path must be specified.',
];
}

/**
* @return array{file: string, contents: string}
*/
public function validated(): array
{
$data = parent::validated();

return [
'file' => (string) $data['file'],
'contents' => (string) $data['contents'],
];
}
}
Loading

0 comments on commit 6c64084

Please sign in to comment.