Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
44e1e4a293 | ||
| ad92a4c434 | |||
|
|
be12175e17 | ||
| e8fc85c173 | |||
|
|
b39e6f81d8 | ||
| 28690be509 |
@@ -1,2 +1,2 @@
|
||||
parameters:
|
||||
app.version: '0.1.2'
|
||||
app.version: '0.1.5'
|
||||
|
||||
@@ -6,7 +6,7 @@ export function useAppVersion() {
|
||||
if (version.value) {
|
||||
return version.value
|
||||
}
|
||||
const response = await api.get<{ version: string }>('version', {}, {
|
||||
const response = await api.get<{ version: string }>('/version', {}, {
|
||||
toast: false
|
||||
})
|
||||
version.value = response.version
|
||||
|
||||
@@ -11,7 +11,7 @@ COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
|
||||
|
||||
WORKDIR /app
|
||||
COPY composer.json composer.lock symfony.lock ./
|
||||
RUN APP_ENV=prod APP_DEBUG=0 COMPOSER_IPRESOLVE=4 composer install --no-dev --no-scripts --no-interaction
|
||||
RUN APP_ENV=prod APP_DEBUG=0 composer install --no-dev --no-scripts --no-interaction
|
||||
|
||||
COPY bin bin/
|
||||
COPY config config/
|
||||
@@ -26,7 +26,6 @@ FROM node:lts-alpine AS frontend-build
|
||||
|
||||
WORKDIR /app/frontend
|
||||
COPY frontend/package.json frontend/package-lock.json ./
|
||||
ENV NODE_OPTIONS=--dns-result-order=ipv4first
|
||||
RUN npm ci
|
||||
|
||||
COPY frontend/ ./
|
||||
|
||||
66
src/Command/CreateUserCommand.php
Normal file
66
src/Command/CreateUserCommand.php
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Command;
|
||||
|
||||
use App\Entity\User;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
|
||||
|
||||
#[AsCommand(
|
||||
name: 'app:create-user',
|
||||
description: 'Create a new user',
|
||||
)]
|
||||
final class CreateUserCommand extends Command
|
||||
{
|
||||
public function __construct(
|
||||
private readonly EntityManagerInterface $em,
|
||||
private readonly UserPasswordHasherInterface $passwordHasher,
|
||||
) {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
protected function configure(): void
|
||||
{
|
||||
$this
|
||||
->addArgument('username', InputArgument::REQUIRED, 'Username')
|
||||
->addArgument('password', InputArgument::REQUIRED, 'Plain text password')
|
||||
->addOption('admin', 'a', InputOption::VALUE_NONE, 'Grant ROLE_ADMIN');
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
|
||||
$username = $input->getArgument('username');
|
||||
$plainPassword = $input->getArgument('password');
|
||||
|
||||
$existing = $this->em->getRepository(User::class)->findOneBy(['username' => $username]);
|
||||
|
||||
if ($existing) {
|
||||
$io->error(sprintf('User "%s" already exists.', $username));
|
||||
|
||||
return Command::FAILURE;
|
||||
}
|
||||
|
||||
$user = new User();
|
||||
$user->setUsername($username);
|
||||
$user->setPassword($this->passwordHasher->hashPassword($user, $plainPassword));
|
||||
$user->setRoles($input->getOption('admin') ? ['ROLE_ADMIN'] : []);
|
||||
|
||||
$this->em->persist($user);
|
||||
$this->em->flush();
|
||||
|
||||
$io->success(sprintf('User "%s" created%s.', $username, $input->getOption('admin') ? ' (admin)' : ''));
|
||||
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -28,9 +28,11 @@ use Symfony\Component\Serializer\Attribute\Groups;
|
||||
normalizationContext: ['groups' => ['me:read']],
|
||||
),
|
||||
new Get(
|
||||
security: "is_granted('ROLE_ADMIN')",
|
||||
normalizationContext: ['groups' => ['user:list']],
|
||||
),
|
||||
new GetCollection(
|
||||
security: "is_granted('ROLE_ADMIN')",
|
||||
normalizationContext: ['groups' => ['user:list']],
|
||||
),
|
||||
new Post(security: "is_granted('ROLE_ADMIN')", processor: UserPasswordHasherProcessor::class),
|
||||
|
||||
@@ -44,13 +44,17 @@ final readonly class MaintenanceToggleProcessor implements ProcessorInterface
|
||||
if ($data->maintenance) {
|
||||
$directory = dirname($maintenancePath);
|
||||
|
||||
if (!is_dir($directory)) {
|
||||
mkdir($directory, 0755, true);
|
||||
if (!is_dir($directory) && !mkdir($directory, 0755, true)) {
|
||||
throw new \RuntimeException(sprintf('Cannot create directory "%s".', $directory));
|
||||
}
|
||||
|
||||
touch($maintenancePath);
|
||||
if (!touch($maintenancePath)) {
|
||||
throw new \RuntimeException(sprintf('Cannot create maintenance file at "%s".', $maintenancePath));
|
||||
}
|
||||
} elseif (file_exists($maintenancePath)) {
|
||||
unlink($maintenancePath);
|
||||
if (!unlink($maintenancePath)) {
|
||||
throw new \RuntimeException(sprintf('Cannot remove maintenance file at "%s".', $maintenancePath));
|
||||
}
|
||||
}
|
||||
|
||||
$dto = new ManagedApplication();
|
||||
|
||||
@@ -8,6 +8,7 @@ use ApiPlatform\Metadata\Operation;
|
||||
use ApiPlatform\State\ProviderInterface;
|
||||
use App\Entity\User;
|
||||
use Symfony\Bundle\SecurityBundle\Security;
|
||||
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
||||
|
||||
/**
|
||||
* @implements ProviderInterface<User>
|
||||
@@ -20,7 +21,12 @@ final readonly class MeProvider implements ProviderInterface
|
||||
|
||||
public function provide(Operation $operation, array $uriVariables = [], array $context = []): User
|
||||
{
|
||||
// @var User $user
|
||||
return $this->security->getUser();
|
||||
$user = $this->security->getUser();
|
||||
|
||||
if (!$user instanceof User) {
|
||||
throw new AccessDeniedHttpException('User not authenticated.');
|
||||
}
|
||||
|
||||
return $user;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user