Completed
Push — master ( ee29b8...f26b67 )
by Jeff
02:51
created

InitSetupCommand::getPassword()   B

Complexity

Conditions 3
Paths 2

Size

Total Lines 30
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 30
rs 8.8571
c 0
b 0
f 0
cc 3
eloc 15
nc 2
nop 3
1
<?php
2
3
declare(strict_types=1);
4
/**
5
 * This file is part of the mailserver-admin package.
6
 * (c) Jeffrey Boehm <https://github.com/jeboehm/mailserver-admin>
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace App\Command;
12
13
use App\Entity\Domain;
14
use App\Entity\User;
15
use App\Service\PasswordService;
16
use Doctrine\ORM\EntityManagerInterface;
17
use Symfony\Component\Console\Command\Command;
18
use Symfony\Component\Console\Helper\QuestionHelper;
19
use Symfony\Component\Console\Input\InputInterface;
20
use Symfony\Component\Console\Output\OutputInterface;
21
use Symfony\Component\Console\Question\Question;
22
use Symfony\Component\Validator\ConstraintViolation;
23
use Symfony\Component\Validator\Validator\ValidatorInterface;
24
25
class InitSetupCommand extends Command
26
{
27
    private $validator;
28
29
    private $entityManager;
30
31
    private $passwordService;
32
33
    public function __construct(
34
        string $name = null,
35
        ValidatorInterface $validator,
36
        EntityManagerInterface $entityManager,
37
        PasswordService $passwordService
38
    ) {
39
        parent::__construct($name);
40
41
        $this->validator = $validator;
42
        $this->entityManager = $entityManager;
43
        $this->passwordService = $passwordService;
44
    }
45
46
    protected function configure(): void
47
    {
48
        $this
49
            ->setName('init:setup')
50
            ->setDescription('Does an initially setup for docker-mailserver.');
51
    }
52
53
    protected function execute(InputInterface $input, OutputInterface $output): int
54
    {
55
        /** @var QuestionHelper $questionHelper */
56
        $questionHelper = $this->getHelper('question');
57
        $output
58
            ->writeln(
59
                [
60
                    '<info>Welcome to docker-mailserver!</info>',
61
                    '<info>This tool will help you to set up the first mail account.</info>',
62
                    '<info>You just have to answer a few questions.</info>',
63
                ]
64
            );
65
66
        [$localPart, $domainPart] = $this->getEmailAddress($questionHelper, $input, $output);
67
        $password = $this->getPassword($questionHelper, $input, $output);
68
69
        $domain = new Domain();
70
        $domain->setName($domainPart);
71
72
        $user = new User();
73
        $user->setName($localPart);
74
        $user->setPlainPassword($password);
75
        $user->setAdmin(true);
76
        $user->setDomain($domain);
77
78
        $domainValidationList = $this->validator->validate($domain);
79
        $userValidationList = $this->validator->validate($user);
80
81
        if ($domainValidationList->count() > 0) {
82
            foreach ($domainValidationList as $item) {
83
                /* @var $item ConstraintViolation */
84
                $output->writeln(
85
                    sprintf('<error>Domain %s: %s</error>', $item->getPropertyPath(), $item->getMessage())
86
                );
87
            }
88
89
            $output->writeln('<error>There were some errors. Please start over again.</error>');
90
91
            return 1;
92
        }
93
94
        if ($userValidationList->count() > 0) {
95
            foreach ($userValidationList as $item) {
96
                /* @var $item ConstraintViolation */
97
                $output->writeln(
98
                    sprintf('<error>User %s: %s</error>', $item->getPropertyPath(), $item->getMessage())
99
                );
100
            }
101
102
            $output->writeln('<error>There were some errors. Please start over again.</error>');
103
104
            return 1;
105
        }
106
107
        $this->passwordService->processUserPassword($user);
108
109
        $this->entityManager->persist($domain);
110
        $this->entityManager->persist($user);
111
112
        $this->entityManager->flush();
113
114
        $output->writeln(sprintf('<info>Your new email address %s was successfully created.</info>', $user));
115
        $output->writeln('<info>You can now login using the previously set password.</info>');
116
117
        return 0;
118
    }
119
120
    private function getEmailAddress(
121
        QuestionHelper $questionHelper,
122
        InputInterface $input,
123
        OutputInterface $output
124
    ): array {
125
        $emailQuestion = new Question('Please enter the first email address you want to receive mails to: ');
126
        $emailQuestion->setValidator(
127
            function (string $value): string {
128
                if (!$value = \filter_var($value, \FILTER_VALIDATE_EMAIL)) {
129
                    throw new \RuntimeException('Please enter a valid email address.');
130
                }
131
132
                return $value;
133
            }
134
        );
135
136
        $email = $questionHelper->ask(
137
            $input,
138
            $output,
139
            $emailQuestion
140
        );
141
142
        return \explode('@', $email);
143
    }
144
145
    private function getPassword(
146
        QuestionHelper $questionHelper,
147
        InputInterface $input,
148
        OutputInterface $output
149
    ): string {
150
        $passwordQuestion = new Question('Enter a password for the new account: ');
151
        $passwordQuestion->setValidator(
152
            function (string $value): string {
153
                if (\mb_strlen($value) < 8) {
154
                    throw new \RuntimeException('The password should be longer.');
155
                }
156
157
                return $value;
158
            }
159
        );
160
        $passwordQuestion->setHidden(true);
161
162
        $repeatPasswordQuestion = new Question('Repeat the password: ');
163
        $repeatPasswordQuestion->setHidden(true);
164
165
        $password1 = $questionHelper->ask($input, $output, $passwordQuestion);
166
        $password2 = $questionHelper->ask($input, $output, $repeatPasswordQuestion);
167
168
        if ($password1 !== $password2) {
169
            $output->writeln('<error>The passwords do not match.</error>');
170
171
            return $this->getPassword($questionHelper, $input, $output);
172
        }
173
174
        return $password1;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $password1 could return the type null|boolean which is incompatible with the type-hinted return string. Consider adding an additional type-check to rule them out.
Loading history...
175
    }
176
}
177