<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Validator\Validator\ValidatorInterface;
use Knp\Component\Pager\PaginatorInterface;
use App\Form\RoleEditPostmaster;
use App\Form\RoleNew;
use App\Form\QAdmin\AliasEdit;
use App\Form\QAdmin\AliasNew;
use App\Form\QAdmin\DomainNew;
use App\Form\QAdmin\DomainSettings;
use App\Form\QAdmin\Settings;
use App\Form\QAdmin\SystemSettings;
use App\Model\Account;
use App\Model\Domain;
use App\Util\Api;
use App\Util\AppLogger;
use App\Util\AccountTools;
use App\Form\QAdmin\DomainsMass;
use App\Model\LicenseServer;
class QAdminController extends AbstractController
{
private $logger;
private $translator;
private $security;
private $params;
private $session;
private $skin;
private $requestStack;
public function __construct(AppLogger $logger, TranslatorInterface $translator, Security $security,
ParameterBagInterface $params, RequestStack $requestStack)
{
$this->logger = $logger;
$this->translator = $translator;
$this->security = $security;
$this->params = $params;
$this->requestStack = $requestStack;
$this->session = $this->requestStack->getSession();
$defaultSkin = 'raw';
if(isset($_SERVER['DEFAULT_SKIN'])) {
$defaultSkin = $_SERVER['DEFAULT_SKIN'];
}
$account = $this->security->getUser()->getAccount();
if(!is_null($account)) { // may be null for superadmin
$this->skin = $account->findSOption('cfgSkin') == null ? $defaultSkin : $account->findSOption('cfgSkin');
}
else {
$this->skin = $defaultSkin;
}
// check if license module should be active
$licenseModuleEnabled = false;
// if there is a DSN defined
if(in_array('ROLE_SUPER_ADMIN', $this->security->getUser()->getRoleNames()) && isset($_SERVER['LICENSE_SRV_DSN'])) {
$ls = new LicenseServer();
$licenseModuleEnabled = $ls->shouldBeEnabled();
}
$this->session->set('license_module_enabled', $licenseModuleEnabled);
QUserController::overwriteEnvs();
}
/**
* @Route("/admin", name="qa_main")
*/
public function index()
{
$health = [];
foreach(["api", "database", "quota"] as $v) {
$health[$v] = Api::checkSystemHealth($v);
}
if($health['api']) {
$version = Api::getVersion();
}
else {
$version = 'unknown';
}
$showVersionWarning = true;
if(isset($_SERVER['APP_ADMINPANEL_SHOW_VERSION_WARNING']) && $_SERVER['APP_ADMINPANEL_SHOW_VERSION_WARNING'] == 'false') {
$showVersionWarning = false;
}
return $this->render('skins/' . $this->skin . '/q_admin/index.html.twig', [
'systemHealth' => $health,
'apiVersion' => $version,
'appVersion' => $this->params->get('app.version.admin'),
'showVersionWarning' => $showVersionWarning,
]);
}
/**
* list of roles
* @Route("/admin/roles", name="qa_roles")
*/
public function roles(Request $request, PaginatorInterface $paginator)
{
$account = $this->security->getUser()->getAccount();
$this->denyAccessUnlessGranted('ADMIN_ROLES_SHOW', $account);
try{
$accounts = Api::listSpecialAccounts();
}
catch(\Exception $e) {
$this->logger->log('Api::listSpecialAccounts() - exception from API', $request, ['error_code' => $e->getCode(), 'error_message' => $e->getMessage()], 'critical');
$this->addFlash('error', $this->translator->trans('Critical error, contact administrator.'));
$accounts = [];
}
return $this->render('skins/' . $this->skin . '/q_admin/roles.html.twig', [
'accounts' => $accounts,
]);
}
/**
* it's not only for new roles, also for editing existing role
* @Route("/admin/roles/new/{userName}/{userDomain}/{token}", defaults={"userName"="", "userDomain"="", "token"=""}, name="qa_roles_new_role")
*/
public function roleNew(string $userName="", string $userDomain="", string $token="", Request $request)
{
$account = $this->security->getUser()->getAccount();
$this->denyAccessUnlessGranted('ADMIN_ROLES_NEW', $account);
if($userName != "") {
$accountEditing = Api::getAccount($userName, $userDomain);
if($token != $accountEditing->token()) {
throw $this->createAccessDeniedException('Invalid token');
}
}
$form = $this->createForm(RoleNew::class);
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()) {
if($form->get('cancel')->isClicked()) {
Api::clearRolesTmpData($this->security->getUser()->getEmail() . $userName . $userDomain);
$this->addFlash('error', $this->translator->trans('Operation cancelled'));
return $this->redirectToRoute("qa_roles");
}
else {
$data = $form->getData();
$account = Api::getAccount($data['accounts'], $data['domains']);
// echo "<pre>";
// var_dump($data);
// exit;
if(($data['roles'] == 'ROLE_POSTMASTER') && ($account->getUserName() == 'postmaster')) {
// for native postmaster we don't need ROLE_POSTMASTER being set
$account->setRole('');
}
else {
$account->setRole($data['roles']);
}
$allOK = false;
if(Api::saveAccountParameters($account) ) {
if(($data['roles'] == 'ROLE_POSTMASTER_MANY') ||
($data['roles'] == 'ROLE_GROUPMASTER') ||
($data['roles'] == 'ROLE_USERMASTER')
) {
if(Api::setRoleDomains($account, $data['domainsForRole'])) {
if($data['roles'] == 'ROLE_GROUPMASTER' || $data['roles'] == 'ROLE_USERMASTER') {
if(Api::setRoleAccounts($account, $data['accountsForRole'])) {
$allOK = true;
}
}
else {
if(Api::deleteRoleAccounts($account)) {
$allOK = true;
}
}
}
}
else {
if(Api::deleteRoleDomains($account)) {
if(Api::deleteRoleAccounts($account)) {
$allOK = true;
}
}
}
}
if($allOK) {
Api::clearRolesTmpData($this->security->getUser()->getEmail() . $userName . $userDomain);
$this->addFlash('notice', $this->translator->trans('New role assigned'));
return $this->redirectToRoute("qa_roles");
}
else {
$this->addFlash('error', $this->translator->trans('New role NOT assigned'));
}
}
}
elseif($form->isSubmitted() && !$form->isValid()){
$this->addFlash('error', $this->translator->trans('New role NOT assigned'));
}
return $this->render('skins/' . $this->skin . '/q_admin/role_new.html.twig', [
'form' => $form->createView(),
'userName' => $userName,
'userDomain' => $userDomain,
]);
}
/**
* @Route("/admin/roles/del/{userName}/{userDomain}/{token}", name="qa_roles_del_role")
*/
public function roleDelete($userName, $userDomain, $token, Request $request)
{
$account = $this->security->getUser()->getAccount();
$this->denyAccessUnlessGranted('ADMIN_ROLES_DELETE', $account);
try {
$account = Api::getAccount($userName, $userDomain);
if($token != $account->token()) {
throw $this->createAccessDeniedException('Invalid token');
}
$allOK = true;
if($account->getRole() == 'ROLE_GROUPMASTER') {
if(!Api::setRoleAccounts($account, [])) {
$allOK = false;
}
}
if(($account->getRole() == 'ROLE_GROUPMASTER') || ($account->getRole() == 'ROLE_POSTMASTER_MANY')) {
if(!Api::setRoleDomains($account, [])) {
$allOK = false;
}
}
$account->setRole('ROLE_USER');
if(!Api::saveAccountParameters($account)) {
$allOK = false;
}
if($allOK) {
$this->addFlash('notice', $this->translator->trans('Role deleted'));
}
else {
$this->addFlash('error', $this->translator->trans("Couldn't delete the role"));
}
}
catch(\Exception $e) {
$this->logger->log('Api::getAccount() or Api::saveAccountParameters() - exception from API', $request, ['error_code' => $e->getCode(), 'error_message' => $e->getMessage()], 'critical');
$this->addFlash('error', $this->translator->trans('Critical error, contact administrator.'));
return $this->redirectToRoute("qa_main");
}
return $this->redirectToRoute("qa_roles");
}
/**
* @Route("/admin/roles/info/{userName}/{userDomain}/{token}", name="qa_roles_info")
*/
public function roleInfo($userName, $userDomain, $token, Request $request)
{
$account = $this->security->getUser()->getAccount();
$this->denyAccessUnlessGranted('ADMIN_ROLES_SHOW', $account);
try {
$account = Api::getAccount($userName, $userDomain);
$domains = Api::getRoleDomains($userName, $userDomain);
$accounts = AccountTools::orderByDomains(Api::getRoleAccounts($userName, $userDomain));
}
catch(\Exception $e) {
$this->logger->log('Api getAccount() or getRoleDomains() - exception from API', $request, ['error_code' => $e->getCode(), 'error_message' => $e->getMessage()], 'critical');
$this->addFlash('error', $this->translator->trans('Critical error, contact administrator.'));
return $this->redirectToRoute("qa_main");
}
if($token != $account->token()) {
throw $this->createAccessDeniedException('Invalid token');
}
if($account->getRole() != 'ROLE_GROUPMASTER' && $account->getRole() != 'ROLE_USERMASTER') {
throw $this->createAccessDeniedException('Invalid role');
}
return $this->render('skins/' . $this->skin . '/q_admin/role_info.html.twig', [
'account' => $account,
'accounts' => $accounts,
'domains' => $domains,
]);
}
/**
* @Route("/admin/roles/edit-postmaster/{userName}/{userDomain}/{token}", name="deprecated_qa_roles_edit_postmaster")
*/
/*public function roleEditPostmaster($userName, $userDomain, $token, Request $request)
{
$form = $this->createForm(RoleEditPostmaster::class);
$form->handleRequest($request);
if(!$form->isSubmitted()) {
$form->get('domains');
var_dump($x);exit();
}
if($form->isSubmitted() && $form->isValid()) {
}
try {
$account = Api::getAccount($userName, $userDomain);
$domains = Api::getRoleDomains($userName, $userDomain);
}
catch(\Exception $e) {
$this->logger->log('Api::getAccount() or getRoleDomains() - exception from API', $request, ['error_code' => $e->getCode(), 'error_message' => $e->getMessage()], 'critical');
$this->addFlash('error', $this->translator->trans('Critical error, contact administrator.'));
return $this->redirectToRoute("qa_main");
}
if($token != $account->token()) {
throw $this->createAccessDeniedException('Invalid token');
}
if($account->getRole() != 'ROLE_POSTMASTER_MANY') {
throw $this->createAccessDeniedException('Invalid role');
}
return $this->render('skins/' . $this->skin . '/q_admin/role_edit_postmaster.html.twig', [
'account' => $account,
'domains' => $domains,
'form' => $form->createView(),
'perColumn' => 4,
]);
}*/
/**
* @Route("/admin/domains", name="qa_domains")
*/
public function domains(Request $request)
{
$account = $this->security->getUser()->getAccount();
$this->denyAccessUnlessGranted('ADMIN_DOMAINS_SHOW', $account);
$domains = Api::listDomains();
$form = $this->createForm(DomainsMass::class);
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()) {
$selected = $request->request->get('domainMassCheckbox');
$ok = true;
foreach($selected as $domain) {
if($this->security->getUser()->getUserDomainPart() == $domain) {
throw $this->createAccessDeniedException($this->translator->trans("You are not allowed to delete your own domain"));
}
if(Api::deleteDomain($domain)) {
$this->logger->log('domain deleted', $request, ['domain' => $domain]);
}
else {
$this->addFlash('error', $this->translator->trans("Couldn't delete domain") . ' ' . $domain);
$ok = false;
}
}
if($ok) {
$this->addFlash('notice', $this->translator->trans('Domain(s) deleted'));
}
return $this->redirectToRoute('qa_domains');
}
return $this->render('skins/' . $this->skin . '/q_admin/domains.html.twig', [
'domains' => $domains,
'massForm' => $form->createView(),
]);
}
/**
* @Route("/admin/domains/new", name="qa_domains_new_domain")
*/
public function domainNew(Request $request, ValidatorInterface $validator)
{
$account = $this->security->getUser()->getAccount();
$this->denyAccessUnlessGranted('ADMIN_DOMAINS_NEW', $account);
$form = $this->createForm(DomainNew::class);
$form->handleRequest($request);
$domainErrors = [];
if($form->isSubmitted() && $form->isValid()) {
foreach(array_unique(explode(',', $form->get('domains')->getData())) as $domain) {
$testret = 0;
switch(($testret = Api::testAddDomain($domain))) {
case 0: // domain exists or error in name
$this->logger->log('FAILURE while testing - new domain NOT created', $request, ['domain' => $domain]);
$this->addFlash('error', $this->translator->trans('New domains NOT added. Problem with a domain: ') . $domain);
break;
case -1: // error
$this->logger->log('FAILURE while testing - new domain NOT created', $request, ['domain' => $domain]);
$this->addFlash('error', $this->translator->trans('New domains NOT added. Problem with a domain: ') . $domain);
break;
}
if($testret == 0 || $testret == -1) {
return $this->render('skins/' . $this->skin . '/q_admin/domain_new.html.twig', [
'form' => $form->createView(),
'domainErrors' => $domainErrors,
]);
}
}
$domainsAddedArr = [];
foreach(array_unique(explode(',', $form->get('domains')->getData())) as $domain) {
try {
$domain = trim($domain);
Api::addDomain($domain);
// if password provided for postmaster set it now
if($form->get('password')->getData() != '') {
if(!Api::changePassword('postmaster', $domain, $form->get('password')->getData())) {
$this->logger->log('FAILURE while changing password for postmaster', $request, ['domain' => $domain]);
$this->addFlash('warning', $this->translator->trans('New domain(s) added, but password for postmaster not set. Domain: ' . $domain));
}
else {
$this->logger->log('domain added', $request, ['domain' => $domain]);
}
}
else {
$this->logger->log('domain added', $request, ['domain' => $domain]);
}
$domainsAddedArr[] = $domain;
}
catch(\Exception $e) {
$this->logger->log('FAILURE while adding - new domain NOT created', $request, ['domain' => $domain, 'code' => $e->getCode()]);
$this->addFlash('error', $this->translator->trans('New domains NOT added. Problem with a domain: ') . $domain);
return $this->render('skins/' . $this->skin . '/q_admin/domain_new.html.twig', [
'form' => $form->createView(),
'domainErrors' => $domainErrors,
]);
}
}
$this->addFlash('notice', $this->translator->trans('New domain(s) added') . ': ' . implode(', ', $domainsAddedArr));
return $this->redirectToRoute('qa_domains_new_domain');
}
elseif($form->isSubmitted() && !$form->isValid()){
$errors = $form['domains']->getErrors();
// there are errors in usernames field. Check which one is problematic
if(count($errors)) {
foreach(explode(',', $form->get('domains')->getData()) as $d) {
if(!preg_match(Domain::DOMAIN_REGEX, $d)) {
$domainErrors[] = $this->translator->trans('Domain contains illegal characters');
}
else {
if(!preg_match('/\./', $d)) {
$domainErrors[] = $this->translator->trans('Domain name must contain a dot');
}
else {
$testret = Api::testAddDomain($d);
if($testret == 0) {
$domainErrors[] = $this->translator->trans('Domain already exists');
}
elseif($testret == -1) {
$domainErrors[] = $this->translator->trans('Unknown error while adding a domain');
}
else {
$domainErrors[] = '';
}
}
}
}
}
$this->addFlash('error', $this->translator->trans('New domain(s) NOT added'));
}
return $this->render('skins/' . $this->skin . '/q_admin/domain_new.html.twig', [
'form' => $form->createView(),
'domainErrors' => $domainErrors,
]);
}
/**
* @Route("/admin/domains/del/{domain}", name="qa_domains_del_domain")
*/
public function domainDelete($domain, Request $request)
{
$account = $this->security->getUser()->getAccount();
$this->denyAccessUnlessGranted('ADMIN_DOMAINS_SHOW', $account);
// don't allow delete your own domain
if($this->security->getUser()->getUserDomainPart() == $domain) {
throw $this->createAccessDeniedException($this->translator->trans("You are not allowed to delete your own domain"));
}
if(Api::deleteDomain($domain)) {
$this->logger->log('domain deleted', $request, ['domain' => $domain]);
$this->addFlash('notice', $this->translator->trans('Domain deleted'));
}
else {
$this->addFlash('error', $this->translator->trans("Couldn't delete domain"));
}
return $this->redirectToRoute("qa_domains");
}
/**
* @Route("/admin/domains/edit/{domain}", name="qa_domains_edit_domain")
*/
public function domainEdit($domain, Request $request)
{
$account = $this->security->getUser()->getAccount();
$this->denyAccessUnlessGranted('ADMIN_DOMAINS_SHOW', $account);
$form = $this->createForm(DomainSettings::class);
$form->handleRequest($request);
if(!$form->isSubmitted()) {
// restrictQuotaUsage
$form->get('restrictQuotaUsage')->setData('no');
try {
$d = Api::getDomain($domain);
if($d->findOption('restrictQuotaUsage')) {
$form->get('restrictQuotaUsage')->setData('yes');
}
}
catch(\Exception $e) {
}
}
if($form->isSubmitted() && $form->isValid()) {
// check if destination account exists
$success = false;
$d = Api::getDomain($domain);
if($form->get('restrictQuotaUsage')->getData() == 'yes') {
$d->setOption('restrictQuotaUsage', 'yes');
}
else {
$d->deleteOption('restrictQuotaUsage');
}
if(Api::saveDomain($d)) {
$success = true;
$this->logger->log('Settings (parameters) for domain ' . $domain . ' saved', $request, ['accountName' => $account->getUsername()]);
}
else {
$success = false;
$this->logger->log('Error while saving parameters for domain ' . $domain, $request, ['accountName' => $account->getUsername()]);
}
if($success) {
$this->addFlash('notice', $this->translator->trans('Settings saved'));
}
else {
$this->addFlash('error', $this->translator->trans('Settings NOT saved'));
}
return $this->redirectToRoute('qa_domains_edit_domain', ['domain' => $domain]);
}
elseif($form->isSubmitted() && !$form->isValid()){
$this->addFlash('error', $this->translator->trans('Settings NOT saved'));
}
return $this->render('skins/' . $this->skin . '/q_admin/domain_settings.html.twig', [
'form' => $form->createView(),
'domain' => $domain,
]);
}
/**
* @Route("/admin/aliases", name="qa_aliases")
*/
public function aliases(Request $request)
{
$account = $this->security->getUser()->getAccount();
$this->denyAccessUnlessGranted('ADMIN_ALIASES_SHOW', $account);
$aliases = Api::listDomainsAliases();
$form = $this->createForm(DomainsMass::class);
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()) {
$selected = $request->request->get('aliasMassCheckbox');
$ok = true;
foreach($selected as $alias) {
if($this->security->getUser()->getUserDomainPart() == $alias) {
throw $this->createAccessDeniedException($this->translator->trans("You are not allowed to delete your own domain"));
}
if(Api::deleteDomainAlias($alias)) {
$this->logger->log('alias deleted', $request, ['alias' => $alias]);
}
else {
$this->addFlash('error', $this->translator->trans("Couldn't delete alias") . ' ' . $alias);
$ok = false;
}
}
if($ok) {
$this->addFlash('notice', $this->translator->trans('Alias(es) deleted'));
}
return $this->redirectToRoute('qa_aliases');
}
return $this->render('skins/' . $this->skin . '/q_admin/aliases.html.twig', [
'aliases' => $aliases,
'massForm' => $form->createView(),
]);
}
/**
* @Route("/admin/aliases/new", name="qa_aliases_new_alias")
*/
public function aliasNew(Request $request, ValidatorInterface $validator)
{
$account = $this->security->getUser()->getAccount();
$this->denyAccessUnlessGranted('ADMIN_ALIASES_NEW', $account);
$form = $this->createForm(AliasNew::class);
$form->handleRequest($request);
$aliasErrors = [];
if($form->isSubmitted() && $form->isValid()) {
// check if this alias or domain doesn't exist
foreach(explode(',', $form->get('aliases')->getData()) as $alias) {
$testret = 0;
switch(($testret = Api::testAddDomain($alias))) {
case 0: // domain exists or error in name
$this->logger->log('FAILURE while testing - new domain alias NOT created, domain already exists', $request, ['alias' => $alias]);
$this->addFlash('error', $this->translator->trans('New aliases NOT added, domain already exists. Problem with a name: ') . $alias);
break;
case -1: // error
$this->logger->log('FAILURE while testing - new domain alias NOT created', $request, ['alias' => $alias]);
$this->addFlash('error', $this->translator->trans('New alias NOT added. Problem with a name: ') . $alias);
break;
}
if($testret == 0 || $testret == -1) {
return $this->render('skins/' . $this->skin . '/q_admin/alias_new.html.twig', [
'form' => $form->createView(),
'aliasErrors' => $aliasErrors,
]);
}
}
$aliasesAddedArr = [];
$domain = $form->get('domain')->getData();
foreach(explode(',', $form->get('aliases')->getData()) as $alias) {
try {
$alias = trim($alias);
Api::addDomainAlias($alias, $domain);
$this->logger->log('domain alias added', $request, ['alias' => $alias, 'domain' => $domain]);
$aliasesAddedArr[] = $alias;
}
catch(\Exception $e) {
$this->logger->log('FAILURE while adding - new domain alias NOT created', $request, ['alias' => $alias, 'domain' => $domain, 'code' => $e->getCode()]);
$this->addFlash('error', $this->translator->trans('New aliases NOT added. Problem with a name: ') . $alias);
return $this->render('skins/' . $this->skin . '/q_admin/alias_new.html.twig', [
'form' => $form->createView(),
'aliasErrors' => $aliasErrors,
]);
}
}
$this->addFlash('notice', $this->translator->trans('New alias(es) added') . ': ' . implode(', ', $aliasesAddedArr));
return $this->redirectToRoute('qa_aliases_new_alias');
}
elseif($form->isSubmitted() && !$form->isValid()){
$errors = $form['aliases']->getErrors();
//var_dump(count($errors));
/*foreach($errors as $e) {
echo "e msg = " . $e->getMessage();
}
echo "form not valid" ; exit;*/
// there are errors in aliases field. Check which one is problematic
if(count($errors)) {
foreach(explode(',', $form->get('aliases')->getData()) as $a) {
if(!preg_match(Domain::DOMAIN_REGEX, $a)) {
$aliasErrors[] = $this->translator->trans('Alias contains illegal characters');
}
else {
if(!preg_match('/\./', $a)) {
$aliasErrors[] = $this->translator->trans('Alias name must contain a dot');
}
else {
$testret = Api::testAddDomain($a);
if($testret == 0) {
$aliasErrors[] = $this->translator->trans('Domain / alias already exists');
}
elseif($testret == -1) {
$aliasErrors[] = $this->translator->trans('Unknown error while adding an alias');
}
else {
$aliasErrors[] = '';
}
}
}
}
}
$this->addFlash('error', $this->translator->trans('New alias(es) NOT added'));
}
return $this->render('skins/' . $this->skin . '/q_admin/alias_new.html.twig', [
'form' => $form->createView(),
'aliasErrors' => $aliasErrors,
]);
}
/**
* @Route("/admin/aliases/del/{alias}", name="qa_aliases_del_alias")
*/
public function aliasDelete($alias, Request $request)
{
$account = $this->security->getUser()->getAccount();
$this->denyAccessUnlessGranted('ADMIN_ALIASES_SHOW', $account);
if(Api::deleteDomainAlias($alias)) {
$this->logger->log('alias deleted', $request, ['alias' => $alias]);
$this->addFlash('notice', $this->translator->trans('Alias deleted'));
}
else {
$this->addFlash('error', $this->translator->trans("Couldn't delete alias"));
}
return $this->redirectToRoute("qa_aliases");
}
/**
* @Route("/admin/aliases/edit/{alias}/{domain}", name="qa_aliases_edit_alias")
*/
public function aliasEdit($alias, $domain, Request $request)
{
$account = $this->security->getUser()->getAccount();
$this->denyAccessUnlessGranted('ADMIN_ALIASES_SHOW', $account);
$form = $this->createForm(AliasEdit::class);
$form->handleRequest($request);
if(!$form->isSubmitted()) {
// restrictQuotaUsage
$form->get('alias')->setData($alias);
}
if($form->isSubmitted() && $form->isValid()) {
$newAlias = $form->get('alias')->getData();
$success = false;
if($alias == $newAlias) {
$this->addFlash('notice', $this->translator->trans('No change detected'));
}
else {
// check if it's possible to create a new one
switch(Api::testAddDomain($newAlias)) {
case 0: // domain exists or error in name
case -1: // error
$this->addFlash('error', $this->translator->trans('Alias NOT edited, problem with a name'));
return $this->render('skins/' . $this->skin . '/q_admin/alias_edit.html.twig', [
'form' => $form->createView(),
'alias' => $alias,
'domain' => $domain,
]);
break;
}
// remove old alias, create a new one
if(Api::deleteDomainAlias($alias) == false) {
$this->logger->log('Deleting alias ' . $alias . ' for a domain FAILED', $request, ['alias' => $alias]);
$this->addFlash('error', $this->translator->trans('Alias editing error (delete not possible)'));
}
else {
try {
if(Api::addDomainAlias($newAlias, $domain) == false) {
$this->logger->log('Adding alias ' . $alias . ' for a domain ' . $domain . ' FAILED', $request, ['domain' => $domain, 'alias' => $alias]);
$this->addFlash('error', $this->translator->trans('Alias editing error (adding not possible)'));
}
else {
$success = true;
}
}
catch(\Exception $e) {
$this->logger->log('Adding alias ' . $alias . ' for a domain ' . $domain . ' FAILED', $request, ['domain' => $domain, 'alias' => $alias]);
$this->addFlash('error', $this->translator->trans('Alias editing error (adding not possible)'));
}
}
}
if($success) {
$this->addFlash('notice', $this->translator->trans('Changes saved'));
return $this->redirectToRoute('qa_aliases_edit_alias', ['domain' => $domain, 'alias' => $newAlias]);
}
else {
$this->addFlash('error', $this->translator->trans('Changes NOT saved'));
return $this->render('skins/' . $this->skin . '/q_admin/alias_edit.html.twig', [
'form' => $form->createView(),
'alias' => $alias,
'domain' => $domain,
]);
}
}
elseif($form->isSubmitted() && !$form->isValid()){
$this->addFlash('error', $this->translator->trans('Changes NOT saved'));
}
return $this->render('skins/' . $this->skin . '/q_admin/alias_edit.html.twig', [
'form' => $form->createView(),
'alias' => $alias,
'domain' => $domain,
]);
}
/**
* @Route("/admin/logs", name="qa_logs")
*/
public function logs(Request $request)
{
$account = $this->security->getUser()->getAccount();
$this->denyAccessUnlessGranted('ADMIN_LOGS', $account);
$lines = [];
/*$lines[] = ["date" => '2019-08-07 11:56:08', "type" => 'app.INFO', 'message' => 'SUCCESS - user logged in',
'details' => '{"moduleName":"app_login","loggedinUser":"c3@namysql.pl","sessionId":"2dko0njtvdkask236koaq3rdfh"}'
];*/
/*$lines[] = ["date" => '2019-08-07 11:56:08', "level" => 'app.INFO', 'message' => 'SUCCESS - user logged in',
'details' => ["moduleName" => "app_login", "loggedinUser" => "c3@namysql.pl",
"sessionId" => "2dko0njtvdkask236koaq3rdfh"]
];*/
return $this->render('skins/' . $this->skin . '/q_admin/logs.html.twig', [
'lines' => $lines,
]);
}
/**
* @Route("/admin/system/settings", name="qa_system_settings")
*/
public function systemSettings(Request $request)
{
$account = $this->security->getUser()->getAccount();
$this->denyAccessUnlessGranted('ADMIN_SYSTEM_SETTINGS', $account);
$account = $this->security->getUser()->getAccount();
$form = $this->createForm(SystemSettings::class);
$form->handleRequest($request);
if(!$form->isSubmitted()) {
/* $form->get('restrictQuotaUsage')->setData('no');
try {
$d = Api::getDomain($domain);
if($d->findOption('restrictQuotaUsage')) {
$form->get('restrictQuotaUsage')->setData('yes');
}
}
catch(\Exception $e) {
}*/
}
if($form->isSubmitted() && $form->isValid()) {
// check if destination account exists
/*$success = false;
$d = Api::getDomain($domain);
if($form->get('restrictQuotaUsage')->getData() == 'yes') {
$d->setOption('restrictQuotaUsage', 'yes');
}
else {
$d->deleteOption('restrictQuotaUsage');
}
if(Api::saveDomain($d)) {
$success = true;
$this->logger->log('Settings (parameters) for domain ' . $domain . ' saved', $request, ['accountName' => $account->getUsername()]);
}
else {
$success = false;
$this->logger->log('Error while saving parameters for domain ' . $domain, $request, ['accountName' => $account->getUsername()]);
}
if($success) {
$this->addFlash('notice', $this->translator->trans('Settings saved'));
}
else {
$this->addFlash('error', $this->translator->trans('Settings NOT saved'));
}*/
return $this->redirectToRoute('qa_system_settings');
}
elseif($form->isSubmitted() && !$form->isValid()){
$this->addFlash('error', $this->translator->trans('Settings NOT saved'));
}
return $this->render('skins/' . $this->skin . '/q_admin/system_settings.html.twig', [
'form' => $form->createView(),
]);
}
/**
* @Route("/admin/system/status", name="qa_system_status")
*/
public function systemStatus(Request $request)
{
$account = $this->security->getUser()->getAccount();
$this->denyAccessUnlessGranted('ADMIN_SYSTEM_STATUS', $account);
$account = $this->security->getUser()->getAccount();
try {
$status = Api::getSystemStatus();
}
catch(\Exception $e) {
$this->addFlash('error', $this->translator->trans('Error while getting system status'));
return $this->redirectToRoute('qa_main');
}
return $this->render('skins/' . $this->skin . '/q_admin/system_status.html.twig', [
's' => $status,
]);
}
/**
* @Route("/admin/master", name="qa_master")
*/
public function master(Request $request)
{
return $this->render('skins/' . $this->skin . '/q_admin/master.html.twig');
}
/**
* @Route("/admin/panel-info", name="qa_panel_info")
*/
public function panelInfo()
{
$license = Api::getLicense();
$sys = [];
$sys['version'] = $this->params->get('app.version.postmaster');
$sys['apiVersion'] = Api::getVersion();
$sys['apiVersionString'] = Api::getVersionString();
$sys['licensed'] = $license['company'];
$sys['expires'] = $license['expires'];
$sys['plan'] = $license['plan'];
$sys['domains'] = $license['domains'];
return $this->render('skins/' . $this->skin . '/q_admin/panel_info.html.twig', [
'sys' => $sys,
]);
}
/**
* @Route("/admin/charts", name="qa_charts")
*/
public function charts(Request $request)
{
$account = $this->security->getUser()->getAccount();
$this->denyAccessUnlessGranted('ADMIN_CHARTS', $account);
if(isset($_SERVER['APP_CHARTS'])) {
$configArr = AccountTools::envToArray($_SERVER['APP_CHARTS']);
if(is_array($configArr)) {
$chartsConfig = $this->_parseChartsConfig($configArr);
}
else {
$chartsConfig = [];
}
}
else {
$chartsConfig = [];
}
return $this->render('skins/' . $this->skin . '/q_admin/charts.html.twig', [
'config' => $chartsConfig,
]);
}
/**
* generates javascript for charts, depending on .env configuration
* @Route("/app_init_qadmin_charts.js", name="js_init_charts")
*/
public function jsAppInitCharts(Request $request)
{
$account = $this->security->getUser()->getAccount();
$this->denyAccessUnlessGranted('ADMIN_CHARTS', $account);
$js = '';
if(isset($_SERVER['APP_CHARTS'])) {
$chartsConfig = $this->_parseChartsConfig(AccountTools::envToArray($_SERVER['APP_CHARTS']));
}
else {
$chartsConfig = [];
}
$i = 1;
foreach($chartsConfig as $conf) {
$js .= 'let ' . $conf['type'] . $i . ' = new ' . $this->_chartTypeToClass($conf);
$js .= "(c3, initApiEndpoint, '#chart-wrapper" . $i . "'";
// parameters if needed for a type
if($conf['type'] == 'qdisk') {
if(count($conf['params']) > 0) {
$js .= ", '" . $conf['params'][0] . "'";
}
else {
$js .= ", ''";
}
}
elseif($conf['type'] == 'qconnections') {
if(count($conf['params']) > 0) {
$js .= ", [";
foreach($conf['params'] as $param) {
if($param != 'double') {
$js .= "'" . $param . "',";
}
}
$js = rtrim($js, ',');
$js .= "]";
}
else {
$js .= ", []";
}
}
elseif($conf['type'] == 'qmemlines') {
if(count($conf['params']) > 0) {
$js .= ", " . $conf['params'][0];
}
}
$js .= ");\n";
// additional settings
if($conf['type'] == 'qmemlines' || $conf['type'] == 'qmembars') {
$js .= $conf['type'] . $i . ".setTotalMem(initTotalMem);\n";
$js .= $conf['type'] . $i . ".setFixedRange(chartsFixedRange);\n";
}
elseif($conf['type'] == 'qload') {
$js .= $conf['type'] . $i . ".setMaxYAxis(initUserOptions['cfgChartLoadAvgRange']);\n";
$js .= $conf['type'] . $i . ".setFixedRange(chartsFixedRange);\n";
}
$js .= $conf['type'] . $i . ".generateChart();\n";
$js .= $conf['type'] . $i . ".genNewChartData();\n";
$i++;
}
return $this->render('app_init_qadmin_charts.js.twig', [
'js' => $js,
]);
}
/**
* @Route("/admin/settings", name="qa_settings")
*/
public function settings(Request $request)
{
$account = $this->security->getUser()->getAccount();
$form = $this->createForm(Settings::class);
$form->handleRequest($request);
if(!$form->isSubmitted()) {
$chartsFixedRange = $account->findSOption('cfgChartsFixedRange') == null ? 'no' : $account->findSOption('cfgChartsFixedRange');
$chartLoadAvgRange = $account->findSOption('cfgChartLoadAvgRange') == null ? Account::LOAD_AVG_DEFAULT_RANGE : $account->findSOption('cfgChartLoadAvgRange');
$form->get('chartsFixedRange')->setData($chartsFixedRange);
$form->get('chartLoadAvgRange')->setData($chartLoadAvgRange);
}
if($form->isSubmitted() && $form->isValid()) {
$account->setSOption('cfgChartsFixedRange', str_replace(',', '.', $form->get('chartsFixedRange')->getData()));
if($form->get('chartLoadAvgRange')->getData()) {
$account->setSOption('cfgChartLoadAvgRange', $form->get('chartLoadAvgRange')->getData());
}
if(Api::saveAccountParameters($account)) {
$this->addFlash('notice', $this->translator->trans('Settings saved'));
$this->logger->log('Settings for account saved', $request, ['accountName' => $account->getUsername()]);
}
else {
$this->addFlash('error', $this->translator->trans('Settings NOT saved'));
$this->logger->log('Error while saving settings for account', $request, ['accountName' => $account->getUsername()]);
}
return $this->redirectToRoute('qa_settings');
}
elseif($form->isSubmitted() && !$form->isValid()){
$this->addFlash('error', $this->translator->trans('Settings NOT saved'));
}
return $this->render('skins/' . $this->skin . '/q_admin/settings.html.twig', [
'form' => $form->createView(),
]);
}
// parses qchart config returning array of associative arrays
// keys: type: String, params: array
private function _parseChartsConfig(Array $config) : Array
{
$retArr = [];
if(!is_array($config)) {
return $retArr;
}
foreach($config as $conf) {
$elem = [];
$confArr = explode('=', $conf);
$elem['type'] = $confArr[0];
if(sizeof($confArr) > 1) {
$paramsArr = explode(':', $confArr[1]);
$elem['params'] = $paramsArr;
}
else {
$elem['params'] = [];
}
$elem['name'] = $this->_chartTypeToName($elem);
$retArr[] = $elem;
}
return $retArr;
}
private function _chartTypeToName($elem) : String
{
switch($elem['type']) {
case 'qload':
return 'Load avg';
case 'qdisk':
return 'Disk usage';
case 'qqueue':
return 'Mail queue';
case 'qconnections':
return 'SMTP / IMAP4 / POP3 activity';
case 'qmemlines':
if((count($elem['params']) > 0) && ($elem['params'][0] == '0')) {
return 'Free mem';
}
else {
return 'Used mem';
}
case 'qmembars':
return 'Free & Used mem';
}
return 'Unknown';
}
private function _chartTypeToClass($elem) : String
{
switch($elem['type']) {
case 'qload':
return 'QLoadAvg';
case 'qdisk':
return 'QDisk';
case 'qqueue':
return 'QQueue';
case 'qconnections':
return 'QConnections';
case 'qmemlines':
return 'QMemLines';
case 'qmembars':
return 'QMemBars';
}
return 'Unknown';
}
}