Compare commits

...

6 Commits

Author SHA1 Message Date
Quinten
8ebe75b947 fix: composer not been installed in the docker image (#2211) 2026-02-10 16:00:18 -05:00
Hythera
f8144407d1 fix: composer content hash (#2209) 2026-02-09 22:26:01 -05:00
Charles
e431ccb66a add rounding to list-files header (#2207) 2026-02-09 22:19:10 -05:00
Lance Pioch
9291bb4477 Fix webhook processing for event objects (#2198) 2026-02-09 08:47:09 -05:00
Lance Pioch
e8c80ae420 Fix SFTP access denied for subuser when view role is assigned (#2196) 2026-02-09 08:46:47 -05:00
stdpi
f1be003276 Change file browser sticky header again... (#2203) 2026-02-08 15:17:48 -05:00
7 changed files with 60 additions and 5 deletions

View File

@@ -68,6 +68,9 @@ RUN apk add --no-cache \
# required for installing plugins. Pulled from https://github.com/pelican-dev/panel/pull/2034
zip unzip 7zip bzip2-dev yarn git
# Copy composer binary for runtime plugin dependency management
COPY --from=composer /usr/local/bin/composer /usr/local/bin/composer
COPY --chown=root:www-data --chmod=770 --from=composerbuild /build .
COPY --chown=root:www-data --chmod=770 --from=yarnbuild /build/public ./public

View File

@@ -73,6 +73,9 @@ RUN apk add --no-cache \
# required for installing plugins. Pulled from https://github.com/pelican-dev/panel/pull/2034
zip unzip 7zip bzip2-dev yarn git
# Copy composer binary for runtime plugin dependency management
COPY --from=composer /usr/local/bin/composer /usr/local/bin/composer
COPY --chown=root:www-data --chmod=770 --from=composerbuild /build .
COPY --chown=root:www-data --chmod=770 --from=yarnbuild /build/public ./public

View File

@@ -34,6 +34,10 @@ class ProcessWebhook implements ShouldQueue
$data = reset($data);
}
if (is_object($data)) {
$data = get_object_vars($data);
}
if (is_string($data)) {
$data = Arr::wrap(json_decode($data, true) ?? []);
}

View File

@@ -31,13 +31,22 @@ class GetUserPermissionsService
'admin.websocket.transfer',
];
if ($isAdmin) {
return $isOwner || $user->can('update', $server) ? array_merge(['*'], $adminPermissions) : array_merge([SubuserPermission::WebsocketConnect->value], $adminPermissions);
if ($isAdmin && ($isOwner || $user->can('update', $server))) {
return array_merge(['*'], $adminPermissions);
}
/** @var Subuser|null $subuser */
$subuser = $server->subusers()->where('user_id', $user->id)->first();
$subuserPermissions = $subuser !== null ? $subuser->permissions : [];
return $subuser->permissions ?? [];
if ($isAdmin) {
return array_unique(array_merge(
[SubuserPermission::WebsocketConnect->value],
$adminPermissions,
$subuserPermissions,
));
}
return $subuserPermissions;
}
}

2
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "ee0e729079d522f013d1203a624a4765",
"content-hash": "15f89930db77693b2d692dbadf22fb9f",
"packages": [
{
"name": "anourvalar/eloquent-serialize",

View File

@@ -1,10 +1,12 @@
<x-filament-panels::page>
@once
<style>
.files-selection-merged .fi-ta-header-ctn {
.fi-ta-header-ctn {
position: sticky;
top: 0;
z-index: 1;
border-top-left-radius: 15px;
border-top-right-radius: 15px;
-webkit-backdrop-filter: blur(8px);
backdrop-filter: blur(8px);
}

View File

@@ -11,6 +11,7 @@ use App\Models\User;
use App\Models\UserSSHKey;
use App\Tests\Integration\IntegrationTestCase;
use PHPUnit\Framework\Attributes\DataProvider;
use Spatie\Permission\Models\Permission;
class SftpAuthenticationControllerTest extends IntegrationTestCase
{
@@ -195,6 +196,39 @@ class SftpAuthenticationControllerTest extends IntegrationTestCase
$this->post('/api/remote/sftp/auth', $data)->assertForbidden();
}
public function test_subuser_sftp_works_when_user_has_view_only_role(): void
{
[$user, $server] = $this->generateTestAccount([SubuserPermission::FileRead, SubuserPermission::FileSftp]);
$user->update(['password' => password_hash('foobar', PASSWORD_DEFAULT)]);
$this->setAuthorization($server->node);
$data = [
'username' => $user->username . '.' . $server->uuid_short,
'password' => 'foobar',
];
// SFTP works as a plain subuser
$this->postJson('/api/remote/sftp/auth', $data)
->assertOk()
->assertJsonPath('permissions', [SubuserPermission::FileRead->value, SubuserPermission::FileSftp->value]);
// Assign a role with only "view server" permission
$role = Role::findOrCreate('view-only-test', 'web');
$permission = Permission::findOrCreate('view server', 'web');
$role->givePermissionTo($permission);
$user->syncRoles($role);
// SFTP should still work — subuser permissions must be merged with admin permissions
$response = $this->postJson('/api/remote/sftp/auth', $data)
->assertOk();
$permissions = $response->json('permissions');
$this->assertContains(SubuserPermission::FileSftp->value, $permissions);
$this->assertContains(SubuserPermission::FileRead->value, $permissions);
}
public static function authorizationTypeDataProvider(): array
{
return [