Compare commits
3 Commits
e70c6db10f
...
1ab60b99f4
Author | SHA1 | Date | |
---|---|---|---|
1ab60b99f4
|
|||
eb67e4a5eb
|
|||
3d739af292
|
@ -7,12 +7,13 @@ xdebug_enabled: false
|
||||
additional_hostnames: []
|
||||
additional_fqdns: []
|
||||
database:
|
||||
type: mariadb
|
||||
version: "10.11"
|
||||
type: postgres
|
||||
version: "17"
|
||||
use_dns_when_possible: true
|
||||
composer_version: "2"
|
||||
web_environment: []
|
||||
corepack_enable: false
|
||||
host_db_port: "5432"
|
||||
|
||||
# Key features of DDEV's config.yaml:
|
||||
|
||||
|
18
.docker/Dockerfile
Normal file
18
.docker/Dockerfile
Normal file
@ -0,0 +1,18 @@
|
||||
FROM php:8.2-apache
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -qq -y --no-install-recommends \
|
||||
cron \
|
||||
nano \
|
||||
locales coreutils apt-utils git libicu-dev g++ libpng-dev libxml2-dev libzip-dev libonig-dev libxslt-dev;
|
||||
|
||||
RUN echo "en_US.UTF-8 UTF-8" > /etc/locale.gen && locale-gen
|
||||
|
||||
RUN curl -sSk https://getcomposer.org/installer | php -- --disable-tls && \
|
||||
mv composer.phar /usr/local/bin/composer
|
||||
|
||||
RUN docker-php-ext-configure intl
|
||||
RUN docker-php-ext-install pdo pdo_mysql mysqli gd opcache intl zip calendar dom mbstring zip gd xsl && a2enmod rewrite
|
||||
RUN pecl install apcu && docker-php-ext-enable apcu
|
||||
|
||||
WORKDIR /var/www
|
10
.docker/compose.yaml
Normal file
10
.docker/compose.yaml
Normal file
@ -0,0 +1,10 @@
|
||||
services:
|
||||
www:
|
||||
build: .
|
||||
container_name: file-explorer
|
||||
ports:
|
||||
- "8741:80"
|
||||
volumes:
|
||||
- ./hosts:/etc/apache2/sites-enabled
|
||||
- ../:/var/www/project
|
||||
restart: always
|
18
.docker/hosts/server.conf
Normal file
18
.docker/hosts/server.conf
Normal file
@ -0,0 +1,18 @@
|
||||
<VirtualHost *:80>
|
||||
ServerName localhost
|
||||
|
||||
DocumentRoot /var/www/project/public
|
||||
DirectoryIndex /index.php
|
||||
|
||||
<Directory /var/www/project/public>
|
||||
AllowOverride None
|
||||
Order Allow,Deny
|
||||
Allow from All
|
||||
</Directory>
|
||||
|
||||
# <Directory /var/www/project/public/bundles>
|
||||
# FallbackResource disabled
|
||||
# </Directory>
|
||||
ErrorLog /var/log/apache2/project_error.log
|
||||
CustomLog /var/log/apache2/project_access.log combined
|
||||
</VirtualHost>
|
10
.env
10
.env
@ -18,3 +18,13 @@
|
||||
APP_ENV=dev
|
||||
APP_SECRET=bfc9c288ee3dcce80dec8622c2870f27
|
||||
###< symfony/framework-bundle ###
|
||||
|
||||
###> doctrine/doctrine-bundle ###
|
||||
# Format described at https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url
|
||||
# IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml
|
||||
#
|
||||
# DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db"
|
||||
# DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=8.0.32&charset=utf8mb4"
|
||||
# DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=10.11.2-MariaDB&charset=utf8mb4"
|
||||
DATABASE_URL="postgresql://db:db@db:5432/db?serverVersion=16&charset=utf8"
|
||||
###< doctrine/doctrine-bundle ###
|
||||
|
6
.gitignore
vendored
6
.gitignore
vendored
@ -1,5 +1,4 @@
|
||||
/.idea/
|
||||
/data/
|
||||
###> symfony/framework-bundle ###
|
||||
/.env.local
|
||||
/.env.local.php
|
||||
@ -9,8 +8,3 @@
|
||||
/var/
|
||||
/vendor/
|
||||
###< symfony/framework-bundle ###
|
||||
|
||||
###> symfony/asset-mapper ###
|
||||
/public/assets/
|
||||
/assets/vendor/
|
||||
###< symfony/asset-mapper ###
|
||||
|
@ -1,9 +0,0 @@
|
||||
/*
|
||||
* Welcome to your app's main JavaScript file!
|
||||
*
|
||||
* This file will be included onto the page via the importmap() Twig function,
|
||||
* which should already be in your base.html.twig.
|
||||
*/
|
||||
import './styles/app.css';
|
||||
|
||||
console.log('This log comes from assets/app.js - welcome to AssetMapper! 🎉');
|
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M13 9V3.5L18.5 9M6 2c-1.11 0-2 .89-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8l-6-6z"/></svg>
|
Before Width: | Height: | Size: 203 B |
@ -1 +0,0 @@
|
||||
<svg viewBox="0 0 24 24"><path fill="currentColor" d="M4 20q-.825 0-1.412-.587T2 18V6q0-.825.588-1.412T4 4h6l2 2h8q.825 0 1.413.588T22 8v10q0 .825-.587 1.413T20 20z"/></svg>
|
Before Width: | Height: | Size: 173 B |
@ -1,3 +0,0 @@
|
||||
body {
|
||||
background-color: transparent;
|
||||
}
|
@ -7,16 +7,18 @@
|
||||
"php": ">=8.2",
|
||||
"ext-ctype": "*",
|
||||
"ext-iconv": "*",
|
||||
"doctrine/dbal": "^3",
|
||||
"doctrine/doctrine-bundle": "^2.13",
|
||||
"doctrine/doctrine-migrations-bundle": "^3.3",
|
||||
"doctrine/orm": "^3.3",
|
||||
"symfony/apache-pack": "^1.0",
|
||||
"symfony/asset-mapper": "^7.1",
|
||||
"symfony/console": "7.1.*",
|
||||
"symfony/dotenv": "7.1.*",
|
||||
"symfony/finder": "7.1.*",
|
||||
"symfony/flex": "^2",
|
||||
"symfony/framework-bundle": "7.1.*",
|
||||
"symfony/runtime": "7.1.*",
|
||||
"symfony/security-bundle": "7.1.*",
|
||||
"symfony/twig-bundle": "7.1.*",
|
||||
"symfony/ux-icons": "^2.22",
|
||||
"symfony/yaml": "7.1.*",
|
||||
"twig/extra-bundle": "^2.12|^3.0",
|
||||
"twig/twig": "^2.12|^3.0"
|
||||
@ -52,8 +54,7 @@
|
||||
"scripts": {
|
||||
"auto-scripts": {
|
||||
"cache:clear": "symfony-cmd",
|
||||
"assets:install %PUBLIC_DIR%": "symfony-cmd",
|
||||
"importmap:install": "symfony-cmd"
|
||||
"assets:install %PUBLIC_DIR%": "symfony-cmd"
|
||||
},
|
||||
"post-install-cmd": [
|
||||
"@auto-scripts"
|
||||
@ -70,5 +71,10 @@
|
||||
"allow-contrib": false,
|
||||
"require": "7.1.*"
|
||||
}
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/maker-bundle": "^1.61",
|
||||
"symfony/stopwatch": "7.1.*",
|
||||
"symfony/web-profiler-bundle": "7.1.*"
|
||||
}
|
||||
}
|
||||
|
2841
composer.lock
generated
2841
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@ -2,7 +2,11 @@
|
||||
|
||||
return [
|
||||
Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true],
|
||||
Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true],
|
||||
Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true],
|
||||
Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true],
|
||||
Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true],
|
||||
Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
|
||||
Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true],
|
||||
Symfony\UX\Icons\UXIconsBundle::class => ['all' => true],
|
||||
Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true],
|
||||
];
|
||||
|
@ -1,11 +0,0 @@
|
||||
framework:
|
||||
asset_mapper:
|
||||
# The paths to make available to the asset mapper.
|
||||
paths:
|
||||
- assets/
|
||||
missing_import_mode: strict
|
||||
|
||||
when@prod:
|
||||
framework:
|
||||
asset_mapper:
|
||||
missing_import_mode: warn
|
54
config/packages/doctrine.yaml
Normal file
54
config/packages/doctrine.yaml
Normal file
@ -0,0 +1,54 @@
|
||||
doctrine:
|
||||
dbal:
|
||||
url: '%env(resolve:DATABASE_URL)%'
|
||||
|
||||
# IMPORTANT: You MUST configure your server version,
|
||||
# either here or in the DATABASE_URL env var (see .env file)
|
||||
#server_version: '16'
|
||||
|
||||
profiling_collect_backtrace: '%kernel.debug%'
|
||||
use_savepoints: true
|
||||
orm:
|
||||
auto_generate_proxy_classes: true
|
||||
enable_lazy_ghost_objects: true
|
||||
report_fields_where_declared: true
|
||||
validate_xml_mapping: true
|
||||
naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware
|
||||
identity_generation_preferences:
|
||||
Doctrine\DBAL\Platforms\PostgreSQLPlatform: identity
|
||||
auto_mapping: true
|
||||
mappings:
|
||||
App:
|
||||
type: attribute
|
||||
is_bundle: false
|
||||
dir: '%kernel.project_dir%/src/Entity'
|
||||
prefix: 'App\Entity'
|
||||
alias: App
|
||||
controller_resolver:
|
||||
auto_mapping: false
|
||||
|
||||
when@test:
|
||||
doctrine:
|
||||
dbal:
|
||||
# "TEST_TOKEN" is typically set by ParaTest
|
||||
dbname_suffix: '_test%env(default::TEST_TOKEN)%'
|
||||
|
||||
when@prod:
|
||||
doctrine:
|
||||
orm:
|
||||
auto_generate_proxy_classes: false
|
||||
proxy_dir: '%kernel.build_dir%/doctrine/orm/Proxies'
|
||||
query_cache_driver:
|
||||
type: pool
|
||||
pool: doctrine.system_cache_pool
|
||||
result_cache_driver:
|
||||
type: pool
|
||||
pool: doctrine.result_cache_pool
|
||||
|
||||
framework:
|
||||
cache:
|
||||
pools:
|
||||
doctrine.result_cache_pool:
|
||||
adapter: cache.app
|
||||
doctrine.system_cache_pool:
|
||||
adapter: cache.system
|
6
config/packages/doctrine_migrations.yaml
Normal file
6
config/packages/doctrine_migrations.yaml
Normal file
@ -0,0 +1,6 @@
|
||||
doctrine_migrations:
|
||||
migrations_paths:
|
||||
# namespace is arbitrary but should be different from App\Migrations
|
||||
# as migrations classes should NOT be autoloaded
|
||||
'DoctrineMigrations': '%kernel.project_dir%/migrations'
|
||||
enable_profiler: false
|
46
config/packages/security.yaml
Normal file
46
config/packages/security.yaml
Normal file
@ -0,0 +1,46 @@
|
||||
security:
|
||||
# https://symfony.com/doc/current/security.html#registering-the-user-hashing-passwords
|
||||
password_hashers:
|
||||
Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto'
|
||||
# https://symfony.com/doc/current/security.html#loading-the-user-the-user-provider
|
||||
providers:
|
||||
# used to reload user from session & other features (e.g. switch_user)
|
||||
app_user_provider:
|
||||
entity:
|
||||
class: App\Entity\User
|
||||
property: email
|
||||
firewalls:
|
||||
dev:
|
||||
pattern: ^/(_(profiler|wdt)|css|images|js)/
|
||||
security: false
|
||||
main:
|
||||
lazy: true
|
||||
provider: app_user_provider
|
||||
custom_authenticators:
|
||||
- App\Security\Authenticator
|
||||
|
||||
# activate different ways to authenticate
|
||||
# https://symfony.com/doc/current/security.html#the-firewall
|
||||
|
||||
# https://symfony.com/doc/current/security/impersonating_user.html
|
||||
# switch_user: true
|
||||
|
||||
# Easy way to control access for large sections of your site
|
||||
# Note: Only the *first* access control that matches will be used
|
||||
access_control:
|
||||
- { path: /, roles: ROLE_USER}
|
||||
# - { path: ^/admin, roles: ROLE_ADMIN }
|
||||
# - { path: ^/profile, roles: ROLE_USER }
|
||||
|
||||
when@test:
|
||||
security:
|
||||
password_hashers:
|
||||
# By default, password hashers are resource intensive and take time. This is
|
||||
# important to generate secure password hashes. In tests however, secure hashes
|
||||
# are not important, waste resources and increase test times. The following
|
||||
# reduces the work factor to the lowest possible values.
|
||||
Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface:
|
||||
algorithm: auto
|
||||
cost: 4 # Lowest possible value for bcrypt
|
||||
time_cost: 3 # Lowest possible value for argon
|
||||
memory_cost: 10 # Lowest possible value for argon
|
17
config/packages/web_profiler.yaml
Normal file
17
config/packages/web_profiler.yaml
Normal file
@ -0,0 +1,17 @@
|
||||
when@dev:
|
||||
web_profiler:
|
||||
toolbar: true
|
||||
intercept_redirects: false
|
||||
|
||||
framework:
|
||||
profiler:
|
||||
only_exceptions: false
|
||||
collect_serializer_data: true
|
||||
|
||||
when@test:
|
||||
web_profiler:
|
||||
toolbar: false
|
||||
intercept_redirects: false
|
||||
|
||||
framework:
|
||||
profiler: { collect: false }
|
3
config/routes/security.yaml
Normal file
3
config/routes/security.yaml
Normal file
@ -0,0 +1,3 @@
|
||||
_security_logout:
|
||||
resource: security.route_loader.logout
|
||||
type: service
|
8
config/routes/web_profiler.yaml
Normal file
8
config/routes/web_profiler.yaml
Normal file
@ -0,0 +1,8 @@
|
||||
when@dev:
|
||||
web_profiler_wdt:
|
||||
resource: '@WebProfilerBundle/Resources/config/routing/wdt.xml'
|
||||
prefix: /_wdt
|
||||
|
||||
web_profiler_profiler:
|
||||
resource: '@WebProfilerBundle/Resources/config/routing/profiler.xml'
|
||||
prefix: /_profiler
|
@ -1,19 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Returns the importmap for this application.
|
||||
*
|
||||
* - "path" is a path inside the asset mapper system. Use the
|
||||
* "debug:asset-map" command to see the full list of paths.
|
||||
*
|
||||
* - "entrypoint" (JavaScript only) set to true for any module that will
|
||||
* be used as an "entrypoint" (and passed to the importmap() Twig function).
|
||||
*
|
||||
* The "importmap:require" command can be used to add new entries to this file.
|
||||
*/
|
||||
return [
|
||||
'app' => [
|
||||
'path' => './assets/app.js',
|
||||
'entrypoint' => true,
|
||||
],
|
||||
];
|
0
migrations/.gitignore
vendored
Normal file
0
migrations/.gitignore
vendored
Normal file
BIN
public/icon.png
Normal file
BIN
public/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 117 KiB |
@ -2,7 +2,6 @@
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Service\FileSystemService;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
@ -11,10 +10,8 @@ use Symfony\Component\Routing\Attribute\Route;
|
||||
class HomeController extends AbstractController
|
||||
{
|
||||
#[Route(path: '/', name: 'app_home', methods: Request::METHOD_GET)]
|
||||
public function __invoke(
|
||||
FileSystemService $fileSystemService
|
||||
): Response
|
||||
public function home(): Response
|
||||
{
|
||||
return $this->render('home.html.twig', ['content' => $fileSystemService->getDirs()]);
|
||||
return $this->render('index.html.twig');
|
||||
}
|
||||
}
|
0
src/Entity/.gitignore
vendored
Normal file
0
src/Entity/.gitignore
vendored
Normal file
91
src/Entity/User.php
Normal file
91
src/Entity/User.php
Normal file
@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use App\Repository\UserRepository;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
|
||||
#[ORM\Entity(repositoryClass: UserRepository::class)]
|
||||
#[ORM\Table(name: '`user`')]
|
||||
#[ORM\UniqueConstraint(name: 'UNIQ_IDENTIFIER_EMAIL', fields: ['email'])]
|
||||
class User implements UserInterface
|
||||
{
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue]
|
||||
#[ORM\Column]
|
||||
private ?int $id = null;
|
||||
|
||||
#[ORM\Column(length: 180)]
|
||||
private string $email = '';
|
||||
|
||||
#[ORM\Column(length: 255)]
|
||||
private string $name = '';
|
||||
|
||||
#[ORM\Column(length: 255)]
|
||||
private string $username = '';
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getEmail(): string
|
||||
{
|
||||
return $this->email;
|
||||
}
|
||||
|
||||
public function setEmail(string $email): static
|
||||
{
|
||||
$this->email = $email;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getUserIdentifier(): string
|
||||
{
|
||||
return $this->email;
|
||||
}
|
||||
|
||||
public function getRoles(): array
|
||||
{
|
||||
return ['ROLE_USER'];
|
||||
}
|
||||
|
||||
public function eraseCredentials(): void
|
||||
{
|
||||
}
|
||||
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function setName(?string $name): static
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getUsername(): string
|
||||
{
|
||||
return $this->username;
|
||||
}
|
||||
|
||||
public function setUsername(string $username): static
|
||||
{
|
||||
$this->username = $username;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public static function createFromRequest(Request $request): static
|
||||
{
|
||||
return (new self())
|
||||
->setEmail($request->headers->get('x-authentik-email'))
|
||||
->setName($request->headers->get('x-authentik-name'))
|
||||
->setUsername($request->headers->get('x-authentik-username'));
|
||||
}
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Objects;
|
||||
|
||||
use SplFileInfo;
|
||||
|
||||
class DirContent
|
||||
{
|
||||
private function __construct(
|
||||
private readonly string $name,
|
||||
private readonly int $size,
|
||||
private readonly string $type,
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
public static function make(SplFileInfo $fileInfo): DirContent
|
||||
{
|
||||
return new self(
|
||||
$fileInfo->getBasename(),
|
||||
$fileInfo->getSize() ?? 0,
|
||||
$fileInfo->getType() ?? 'N/A',
|
||||
);
|
||||
}
|
||||
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function getSize(bool $humanReadable = true): int|string
|
||||
{
|
||||
if (!$humanReadable) {
|
||||
return $this->size;
|
||||
}
|
||||
|
||||
return $this->getHumanReadableSize();
|
||||
}
|
||||
|
||||
public function getType(): string
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
private function getHumanReadableSize()
|
||||
{
|
||||
$bytes = $this->size;
|
||||
$size = array('B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB');
|
||||
$factor = floor((strlen((string) $bytes) - 1) / 3);
|
||||
|
||||
return sprintf("%.1f %s", $bytes / (1024 ** $factor), $size[$factor]);
|
||||
|
||||
}
|
||||
}
|
0
src/Repository/.gitignore
vendored
Normal file
0
src/Repository/.gitignore
vendored
Normal file
34
src/Repository/UserRepository.php
Normal file
34
src/Repository/UserRepository.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\User;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<User>
|
||||
*/
|
||||
class UserRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, User::class);
|
||||
}
|
||||
|
||||
public function save(User $user): void
|
||||
{
|
||||
$this->getEntityManager()->persist($user);
|
||||
$this->getEntityManager()->flush();
|
||||
}
|
||||
|
||||
public function exists(string $email): bool
|
||||
{
|
||||
return $this->createQueryBuilder('u')
|
||||
->select('COUNT(u.id)')
|
||||
->where('u.email = :email')
|
||||
->setParameter('email', $email)
|
||||
->getQuery()
|
||||
->getSingleScalarResult() === 1;
|
||||
}
|
||||
}
|
68
src/Security/Authenticator.php
Normal file
68
src/Security/Authenticator.php
Normal file
@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace App\Security;
|
||||
|
||||
use App\Entity\User;
|
||||
use App\Repository\UserRepository;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||
use Symfony\Component\Security\Http\Authenticator\AbstractAuthenticator;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\RememberMeBadge;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport;
|
||||
|
||||
class Authenticator extends AbstractAuthenticator
|
||||
{
|
||||
public function __construct(private readonly UserRepository $userRepository)
|
||||
{
|
||||
}
|
||||
|
||||
public function supports(Request $request): ?bool
|
||||
{
|
||||
return $request->headers->has('x-authentik-username')
|
||||
&& $request->headers->has('x-authentik-email')
|
||||
&& $request->headers->has('x-authentik-name');
|
||||
}
|
||||
|
||||
public function authenticate(Request $request): Passport
|
||||
{
|
||||
$email = $request->headers->get('x-authentik-email');
|
||||
|
||||
$this->checkGroup($request);
|
||||
$this->createUserIfNotExists($email, $request);
|
||||
|
||||
return new SelfValidatingPassport(new UserBadge($email), [new RememberMeBadge()]);
|
||||
}
|
||||
|
||||
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response
|
||||
{
|
||||
dd($exception);
|
||||
return new JsonResponse([$exception], Response::HTTP_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
private function createUserIfNotExists(string $email, Request $request): void
|
||||
{
|
||||
if ($this->userRepository->exists($email)) {
|
||||
$user = User::createFromRequest($request);
|
||||
$this->userRepository->save($user);
|
||||
}
|
||||
}
|
||||
|
||||
private function checkGroup(Request $request): void
|
||||
{
|
||||
$groups = explode('|', $request->headers->get('x-authentik-groups'));
|
||||
|
||||
if (!in_array('file-explorer user', $groups)) {
|
||||
throw new \LogicException('You are not allowed to access this resource');
|
||||
}
|
||||
}
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Service;
|
||||
|
||||
use App\Objects\DirContent;
|
||||
use Symfony\Component\DependencyInjection\Attribute\Autowire;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
|
||||
class FileSystemService
|
||||
{
|
||||
public function __construct(
|
||||
#[Autowire(env: 'DATA_DIR')]
|
||||
private readonly string $dir
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return DirContent[]
|
||||
*/
|
||||
public function getDirs(): array
|
||||
{
|
||||
$finder = new Finder();
|
||||
$finder->in($this->dir);
|
||||
|
||||
$contents = [];
|
||||
|
||||
foreach ($finder->depth(0) as $content) {
|
||||
$contents[] = DirContent::make($content);
|
||||
}
|
||||
|
||||
return $contents;
|
||||
}
|
||||
}
|
84
symfony.lock
84
symfony.lock
@ -1,4 +1,31 @@
|
||||
{
|
||||
"doctrine/doctrine-bundle": {
|
||||
"version": "2.13",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "2.13",
|
||||
"ref": "8d96c0b51591ffc26794d865ba3ee7d193438a83"
|
||||
},
|
||||
"files": [
|
||||
"config/packages/doctrine.yaml",
|
||||
"src/Entity/.gitignore",
|
||||
"src/Repository/.gitignore"
|
||||
]
|
||||
},
|
||||
"doctrine/doctrine-migrations-bundle": {
|
||||
"version": "3.3",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "3.1",
|
||||
"ref": "1d01ec03c6ecbd67c3375c5478c9a423ae5d6a33"
|
||||
},
|
||||
"files": [
|
||||
"config/packages/doctrine_migrations.yaml",
|
||||
"migrations/.gitignore"
|
||||
]
|
||||
},
|
||||
"symfony/apache-pack": {
|
||||
"version": "1.0",
|
||||
"recipe": {
|
||||
@ -11,21 +38,6 @@
|
||||
"public/.htaccess"
|
||||
]
|
||||
},
|
||||
"symfony/asset-mapper": {
|
||||
"version": "7.1",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "6.4",
|
||||
"ref": "5ad1308aa756d58f999ffbe1540d1189f5d7d14a"
|
||||
},
|
||||
"files": [
|
||||
"assets/app.js",
|
||||
"assets/styles/app.css",
|
||||
"config/packages/asset_mapper.yaml",
|
||||
"importmap.php"
|
||||
]
|
||||
},
|
||||
"symfony/console": {
|
||||
"version": "7.1",
|
||||
"recipe": {
|
||||
@ -43,11 +55,12 @@
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "1.0",
|
||||
"ref": "146251ae39e06a95be0fe3d13c807bcf3938b172"
|
||||
"version": "2.4",
|
||||
"ref": "52e9754527a15e2b79d9a610f98185a1fe46622a"
|
||||
},
|
||||
"files": [
|
||||
".env"
|
||||
".env",
|
||||
".env.dev"
|
||||
]
|
||||
},
|
||||
"symfony/framework-bundle": {
|
||||
@ -69,6 +82,15 @@
|
||||
"src/Kernel.php"
|
||||
]
|
||||
},
|
||||
"symfony/maker-bundle": {
|
||||
"version": "1.61",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "1.0",
|
||||
"ref": "fadbfe33303a76e25cb63401050439aa9b1a9c7f"
|
||||
}
|
||||
},
|
||||
"symfony/routing": {
|
||||
"version": "7.1",
|
||||
"recipe": {
|
||||
@ -82,6 +104,19 @@
|
||||
"config/routes.yaml"
|
||||
]
|
||||
},
|
||||
"symfony/security-bundle": {
|
||||
"version": "7.1",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "6.4",
|
||||
"ref": "2ae08430db28c8eb4476605894296c82a642028f"
|
||||
},
|
||||
"files": [
|
||||
"config/packages/security.yaml",
|
||||
"config/routes/security.yaml"
|
||||
]
|
||||
},
|
||||
"symfony/twig-bundle": {
|
||||
"version": "7.1",
|
||||
"recipe": {
|
||||
@ -95,19 +130,20 @@
|
||||
"templates/base.html.twig"
|
||||
]
|
||||
},
|
||||
"symfony/ux-icons": {
|
||||
"version": "2.22",
|
||||
"symfony/web-profiler-bundle": {
|
||||
"version": "7.1",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "2.17",
|
||||
"ref": "803a3bbd5893f9584969ab8670290cdfb6a0a5b5"
|
||||
"version": "6.1",
|
||||
"ref": "e42b3f0177df239add25373083a564e5ead4e13a"
|
||||
},
|
||||
"files": [
|
||||
"assets/icons/symfony.svg"
|
||||
"config/packages/web_profiler.yaml",
|
||||
"config/routes/web_profiler.yaml"
|
||||
]
|
||||
},
|
||||
"twig/extra-bundle": {
|
||||
"version": "v3.16.0"
|
||||
"version": "v3.13.0"
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +0,0 @@
|
||||
<tr>
|
||||
<td>
|
||||
{% if file.type == 'dir' %}
|
||||
{{ ux_icon('folder:closed', {height: '32px', width: '32px'}) }}
|
||||
{% else %}
|
||||
{{ ux_icon('file:default', {height: '32px', width: '32px'}) }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ file.name }}</td>
|
||||
<td>{{ file.size }}</td>
|
||||
</tr>
|
@ -1,13 +0,0 @@
|
||||
<table class="table table-striped table-bordered w-75 mt-5">
|
||||
<thead>
|
||||
<tr>
|
||||
<td>Expand</td>
|
||||
<th>Name</th>
|
||||
<th>Size</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for dirContent in content %}
|
||||
{% include '_partials/_row.html.twig' with {file: dirContent} %}
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
@ -1,15 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Files | {% block title %}{% endblock %}</title>
|
||||
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 128 128%22><text y=%221.2em%22 font-size=%2296%22>⚫️</text><text y=%221.3em%22 x=%220.2em%22 font-size=%2276%22 fill=%22%23fff%22>sf</text></svg>">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
|
||||
<link rel="icon" href="icon.png">
|
||||
{% block stylesheets %}
|
||||
{% endblock %}
|
||||
|
||||
{% block javascripts %}
|
||||
{% block importmap %}{{ importmap('app') }}{% endblock %}
|
||||
{% endblock %}
|
||||
</head>
|
||||
<body>
|
||||
|
@ -1,11 +0,0 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Home{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<center class="mt-5">
|
||||
<h1>Welcome to the File Explorer</h1>
|
||||
<p>Use the navigation bar to explore the files and directories.</p>
|
||||
{% include '_partials/_table.html.twig' %}
|
||||
</center>
|
||||
{% endblock %}
|
7
templates/index.html.twig
Normal file
7
templates/index.html.twig
Normal file
@ -0,0 +1,7 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Home{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
{{ app.user.username }}
|
||||
{% endblock %}
|
Reference in New Issue
Block a user