Skip to content

Commit

Permalink
v0.3.1 (#35)
Browse files Browse the repository at this point in the history
* [task-124] Server variables validation & bugfix

* [task-119] Ask for role in creating user command & improvements in error handling

* [task-131] Updated recharge payment title translation in english

* [task-136] Hide product images when are not set

* [task-133] Added crowdin & roadmap to README.md

* [task-137] Fix with translations in email after purchase

* [task-138] Do not show register page if user is logged in

* [task-139] Added product banner

* [v0.3.1] Fixes in product template after merge

* Added crowdin page to CONTRIBUTING.md

---------

Co-authored-by: Konrad Sroga <[email protected]>
  • Loading branch information
pteroca-com and ksroga authored Jan 28, 2025
1 parent ed290df commit dd41834
Show file tree
Hide file tree
Showing 35 changed files with 396 additions and 58 deletions.
4 changes: 4 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ We love new ideas! If you have a feature request, follow these steps:

5. **Start developing!**


## Helping with Translations
We want PteroCA to be accessible to users all over the world. If you're interested in helping translate PteroCA into more languages, you can contribute via our [Crowdin page](https://crowdin.com/project/pteroca). No coding skills are required—just your language expertise!
## License
By contributing to PteroCA, you agree that your contributions will be licensed under the [MIT License](https://github.com/pteroca-com/panel/blob/main/LICENSE).
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,14 @@ Take a look at some screenshots of our intuitive panel interface below:
### Community & Support
Join our [Discord Server](https://discord.gg/Gz5phhuZym) for community support, or visit our [GitHub Issues](https://github.com/pteroca-com/panel/issues) page to report bugs or request features.

### Roadmap
We are continuously working to improve PteroCA.com! Check out the [Roadmap Page](https://pteroca.com/roadmap) for more details.

### Contributing
We welcome contributions! Check out our [Contributing Guide](https://github.com/pteroca-com/panel/blob/main/CONTRIBUTING.md) to get started.

Also, if you're interested in helping translate PteroCA.com into more languages, visit our [Crowdin page](https://crowdin.com/project/pteroca) to contribute.

---

PteroCA.com is an open-source project licensed under the [MIT License](https://github.com/pteroca-com/panel/blob/main/LICENSE).
26 changes: 26 additions & 0 deletions migrations/Version20250128174115.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

declare(strict_types=1);

namespace DoctrineMigrations;

use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;

final class Version20250128174115 extends AbstractMigration
{
public function getDescription(): string
{
return 'Add `banner_path` column to `product` table';
}

public function up(Schema $schema): void
{
$this->addSql('ALTER TABLE product ADD banner_path VARCHAR(255) DEFAULT NULL');
}

public function down(Schema $schema): void
{
$this->addSql('ALTER TABLE product DROP banner_path');
}
}
4 changes: 4 additions & 0 deletions public/assets/css/panel.css
Original file line number Diff line number Diff line change
Expand Up @@ -168,4 +168,8 @@ input#command {

.server-stats-row {
min-width: 300px;
}

.hover-pointer:hover {
cursor: pointer;
}
5 changes: 4 additions & 1 deletion src/Core/Command/CreateNewUserCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace App\Core\Command;

use App\Core\Enum\UserRoleEnum;
use App\Core\Handler\CreateNewUserHandler;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
Expand All @@ -28,6 +29,7 @@ protected function configure(): void
$this
->addArgument('email', InputArgument::REQUIRED, 'User email')
->addArgument('password', InputArgument::REQUIRED, 'User password')
->addArgument('role', InputArgument::OPTIONAL, 'User role', UserRoleEnum::ROLE_USER->name)
;
}

Expand All @@ -37,8 +39,9 @@ protected function execute(InputInterface $input, OutputInterface $output): int

$email = $input->getArgument('email');
$password = $input->getArgument('password');
$role = UserRoleEnum::tryFrom($input->getArgument('role')) ?? UserRoleEnum::ROLE_USER;

$this->createNewUserHandler->setUserCredentials($email, $password);
$this->createNewUserHandler->setUserCredentials($email, $password, $role);
$this->createNewUserHandler->handle();

$io->success('New user created!');
Expand Down
9 changes: 8 additions & 1 deletion src/Core/Controller/Panel/ProductCrudController.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,14 @@ public function configureFields(string $pageName): iterable
->setBasePath($this->getParameter('products_base_path'))
->setUploadDir($uploadDirectory)
->setUploadedFileNamePattern('[slug]-[timestamp].[extension]')
->setRequired(false),
->setRequired(false)
->setHelp($this->translator->trans('pteroca.crud.product.image_help')),
ImageField::new('bannerPath', $this->translator->trans('pteroca.crud.product.banner'))
->setBasePath($this->getParameter('products_base_path'))
->setUploadDir($uploadDirectory)
->setUploadedFileNamePattern('[slug]-[timestamp].[extension]')
->setRequired(false)
->setHelp($this->translator->trans('pteroca.crud.product.banner_help')),

FormField::addTab($this->translator->trans('pteroca.crud.product.server_resources'))
->setIcon('fa fa-server'),
Expand Down
4 changes: 4 additions & 0 deletions src/Core/Controller/RegistrationController.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ public function register(
#[Autowire(service: 'App\Core\Security\UserAuthenticator')]
AuthenticatorInterface $authenticator,
): Response {
if ($this->getUser() !== null) {
return $this->redirectToRoute('panel');
}

$user = new User();
$form = $this->createForm(RegistrationFormType::class, $user);
$form->handleRequest($request);
Expand Down
29 changes: 29 additions & 0 deletions src/Core/DTO/Collection/ServerVariableCollection.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

namespace App\Core\DTO\Collection;

use App\Core\DTO\ServerVariableDTO;

class ServerVariableCollection
{
public function __construct(
private readonly array $variables,
)
{
}

public function getByEnvVariable(string $envVariable): ?ServerVariableDTO
{
$foundVariable = array_filter($this->variables, function (ServerVariableDTO $variable) use ($envVariable) {
return $variable->envVariable === $envVariable;
});
$foundVariable = current($foundVariable);

return $foundVariable ?: null;
}

public function all(): array
{
return $this->variables;
}
}
3 changes: 3 additions & 0 deletions src/Core/DTO/ServerDataDTO.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace App\Core\DTO;

use App\Core\DTO\Collection\ServerVariableCollection;

class ServerDataDTO
{
public function __construct(
Expand All @@ -14,6 +16,7 @@ public function __construct(
public ?array $availableNestEggs,
public bool $hasConfigurableOptions,
public bool $hasConfigurableVariables,
public ServerVariableCollection $serverVariables,
)
{
}
Expand Down
19 changes: 19 additions & 0 deletions src/Core/DTO/ServerVariableDTO.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace App\Core\DTO;

class ServerVariableDTO
{
public function __construct(
public readonly string $name,
public readonly string $description,
public readonly string $envVariable,
public readonly string $defaultValue,
public readonly string $serverValue,
public readonly bool $isUserEditable,
public readonly bool $isUserViewable,
public readonly array $rules,
)
{
}
}
32 changes: 32 additions & 0 deletions src/Core/Entity/Product.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@ class Product
#[Vich\UploadableField(mapping: 'category_images', fileNameProperty: 'imagePath')]
private ?File $imageFile = null;

#[ORM\Column(type: "string", length: 255, nullable: true)]
private ?string $bannerPath = null;

#[Vich\UploadableField(mapping: 'category_banners', fileNameProperty: 'bannerPath')]
private ?File $bannerFile = null;

#[ORM\ManyToOne(targetEntity: Category::class)]
#[ORM\JoinColumn(nullable: true)]
private ?Category $category;
Expand Down Expand Up @@ -334,6 +340,32 @@ public function getImageFile(): ?File
return $this->imageFile;
}

public function getBannerPath(): ?string
{
return $this->bannerPath;
}

public function setBannerPath(?string $bannerPath): self
{
$this->bannerPath = $bannerPath;
return $this;
}

public function setBannerFile(?File $bannerFile = null): void
{
$this->bannerFile = $bannerFile;
if (null !== $bannerFile) {
// It is required that at least one field changes if you are using doctrine
// otherwise the event listeners won't be called and the file is lost
$this->updatedAt = new \DateTime();
}
}

public function getBannerFile(): ?File
{
return $this->bannerFile;
}

public function __toString(): string
{
return $this->name;
Expand Down
6 changes: 3 additions & 3 deletions src/Core/Enum/UserRoleEnum.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

namespace App\Core\Enum;

enum UserRoleEnum
enum UserRoleEnum: string
{
case ROLE_USER;
case ROLE_USER = 'ROLE_USER';

case ROLE_ADMIN;
case ROLE_ADMIN = 'ROLE_ADMIN';
}
34 changes: 34 additions & 0 deletions src/Core/Factory/ServerVariableFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

namespace App\Core\Factory;

use App\Core\DTO\ServerVariableDTO;

class ServerVariableFactory
{
/**
* @return array<ServerVariableDTO
*/
public function createFromCollection(array $variables): array
{
$preparedVariables = [];

foreach ($variables as $variable) {
$variable = $variable['attributes'];
$variableRules = explode('|', $variable['rules']);

$preparedVariables[] = new ServerVariableDTO(
$variable['name'],
$variable['description'],
$variable['env_variable'],
$variable['default_value'],
$variable['server_value'],
$variable['user_editable'],
$variable['user_viewable'],
$variableRules,
);
}

return $preparedVariables;
}
}
19 changes: 16 additions & 3 deletions src/Core/Handler/CreateNewUserHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,16 @@
use App\Core\Service\Pterodactyl\PterodactylAccountService;
use App\Core\Service\Pterodactyl\PterodactylClientApiKeyService;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
use Timdesm\PterodactylPhpApi\Exceptions\ValidationException;

class CreateNewUserHandler implements HandlerInterface
{
private string $userEmail;

private string $userPassword;

private UserRoleEnum $userRole;

public function __construct(
private readonly UserPasswordHasherInterface $passwordHasher,
private readonly UserRepository $userRepository,
Expand All @@ -32,14 +35,23 @@ public function handle(): void
$user = (new User())
->setEmail($this->userEmail)
->setPassword('')
->setRoles([UserRoleEnum::ROLE_USER->name, UserRoleEnum::ROLE_ADMIN->name])
->setRoles([$this->userRole->name])
->setBalance(0)
->setName('Admin')
->setSurname('Admin');

$hashedPassword = $this->passwordHasher->hashPassword($user, $this->userPassword);
$user->setPassword($hashedPassword);

$pterodactylAccount = $this->pterodactylAccountService->createPterodactylAccount($user, $this->userPassword);
try {
$pterodactylAccount = $this->pterodactylAccountService->createPterodactylAccount($user, $this->userPassword);
} catch (ValidationException $exception) {
$errors = $exception->errors()['errors'] ?? [];
$errors = array_map(fn($error) => $error['detail'], $errors);
$message = sprintf('%s Errors: %s', $exception->getMessage(), implode(', ', $errors));
throw new \RuntimeException($message);
}

if (!empty($pterodactylAccount->id)) {
$user->setPterodactylUserId($pterodactylAccount->id);

Expand All @@ -55,9 +67,10 @@ public function handle(): void
$this->userRepository->save($user);
}

public function setUserCredentials(string $email, string $password): void
public function setUserCredentials(string $email, string $password, UserRoleEnum $userRole): void
{
$this->userEmail = $email;
$this->userPassword = $password;
$this->userRole = $userRole;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace App\Core\Handler\Installer;

use App\Core\Enum\SettingEnum;
use App\Core\Enum\UserRoleEnum;
use App\Core\Repository\SettingRepository;
use App\Core\Service\System\EnvironmentConfigurationService;
use Symfony\Component\Console\Style\SymfonyStyle;
Expand Down Expand Up @@ -34,8 +35,10 @@ private function askForConfigureUser(SymfonyStyle $io): void

$email = $io->ask('User e-mail', '');
$password = $io->ask('User password', '');
$isAdmin = $io->ask('Is user admin? (yes/no)', 'yes') === 'yes';

exec(sprintf('php bin/console app:create-new-user %s %s', $email, $password));
$userRole = $isAdmin ? UserRoleEnum::ROLE_ADMIN : UserRoleEnum::ROLE_USER;
exec(sprintf('php bin/console app:create-new-user %s %s %s', $email, $password, $userRole->name));
}
}

Expand Down
9 changes: 7 additions & 2 deletions src/Core/Resources/translations/messages.cn.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,8 @@ pteroca:
console_token_expired: '控制台令牌已过期。请刷新页面。'
console_connection_closed: '控制台连接已关闭。'
console_connection_error: '连接控制台时发生错误。'
rules: '规则'
data_validation_error: '验证过程中出错。请检查是否满足所有规则。'

actions:
login: '登录'
Expand Down Expand Up @@ -252,6 +254,9 @@ pteroca:
is_active: '活跃'
category: '类别'
image: '图片'
image_help: '图片将显示在商店中。'
banner: '横幅'
banner_help: '横幅将显示在产品页面上。'
server_resources: '服务器资源'
disk_space: '磁盘空间'
memory: 'RAM 内存'
Expand Down Expand Up @@ -417,8 +422,8 @@ pteroca:
store:
subject: '服务器购买'
server_purchased: '您已在我们的商店购买了一台服务器。'
expiration_date: '到期日期'
product_details: '产品详情'
expiration_date: '到期日期'
product_details: '产品详情'
product_name: '产品名称'
product_price: '产品价格'
server_details: '服务器详情'
Expand Down
Loading

0 comments on commit dd41834

Please sign in to comment.