summaryrefslogtreecommitdiffstats
path: root/modules/setup/application/forms/DatabaseCreationPage.php
blob: f7092a17646100414de7e6d60cf7b04dc40ee4ce (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
<?php
/* Icinga Web 2 | (c) 2014 Icinga Development Team | GPLv2+ */

namespace Icinga\Module\Setup\Forms;

use PDOException;
use Icinga\Web\Form;
use Icinga\Module\Setup\Utils\DbTool;

/**
 * Wizard page to define a database user that is able to create databases and tables
 */
class DatabaseCreationPage extends Form
{
    /**
     * The resource configuration to use
     *
     * @var array
     */
    protected $config;

    /**
     * The required privileges to setup the database
     *
     * @var array
     */
    protected $databaseSetupPrivileges;

    /**
     * The required privileges to operate the database
     *
     * @var array
     */
    protected $databaseUsagePrivileges;

    /**
     * Initialize this page
     */
    public function init()
    {
        $this->setTitle($this->translate('Database Setup', 'setup.page.title'));
        $this->addDescription($this->translate(
            'It seems that either the database you defined earlier does not yet exist and cannot be created'
            . ' using the provided access credentials, the database does not have the required schema to be'
            . ' operated by Icinga Web 2 or the provided access credentials do not have the sufficient '
            . 'permissions to access the database. Please provide appropriate access credentials to solve this.'
        ));
    }

    /**
     * Set the resource configuration to use
     *
     * @param   array   $config
     *
     * @return  $this
     */
    public function setResourceConfig(array $config)
    {
        $this->config = $config;
        return $this;
    }

    /**
     * Set the required privileges to setup the database
     *
     * @param   array   $privileges     The privileges
     *
     * @return  $this
     */
    public function setDatabaseSetupPrivileges(array $privileges)
    {
        $this->databaseSetupPrivileges = $privileges;
        return $this;
    }

    /**
     * Set the required privileges to operate the database
     *
     * @param   array   $privileges     The privileges
     *
     * @return  $this
     */
    public function setDatabaseUsagePrivileges(array $privileges)
    {
        $this->databaseUsagePrivileges = $privileges;
        return $this;
    }

    /**
     * @see Form::createElements()
     */
    public function createElements(array $formData)
    {
        $skipValidation = isset($formData['skip_validation']) && $formData['skip_validation'];
        $this->addElement(
            'text',
            'username',
            array(
                'required'      => false === $skipValidation,
                'label'         => $this->translate('Username'),
                'description'   => $this->translate(
                    'A user which is able to create databases and/or touch the database schema'
                )
            )
        );
        $this->addElement(
            'password',
            'password',
            array(
                'renderPassword'    => true,
                'label'             => $this->translate('Password'),
                'description'       => $this->translate('The password for the database user defined above'),
                'autocomplete'      => 'new-password'
            )
        );

        if ($skipValidation) {
            $this->addSkipValidationCheckbox();
        } else {
            $this->addElement(
                'hidden',
                'skip_validation',
                array(
                    'required'  => true,
                    'value'     => 0
                )
            );
        }
    }

    /**
     * Validate the given form data and check whether the defined user has sufficient access rights
     *
     * @param   array   $data   The data to validate
     *
     * @return  bool
     */
    public function isValid($data)
    {
        if (false === parent::isValid($data)) {
            return false;
        }

        if (isset($data['skip_validation']) && $data['skip_validation']) {
            return true;
        }

        $config = $this->config;
        $config['username'] = $this->getValue('username');
        $config['password'] = $this->getValue('password');
        $db = new DbTool($config);

        try {
            $db->connectToDb(); // Are we able to login on the database?
        } catch (PDOException $_) {
            try {
                $db->connectToHost(); // Are we able to login on the server?
            } catch (PDOException $e) {
                // We are NOT able to login on the server..
                $this->error($e->getMessage());
                $this->addSkipValidationCheckbox();
                return false;
            }
        }

        // In case we are connected the credentials filled into this
        // form need to be granted to create databases, users...
        if (false === $db->checkPrivileges($this->databaseSetupPrivileges)) {
            $this->error(
                $this->translate('The provided credentials cannot be used to create the database and/or the user.')
            );
            $this->addSkipValidationCheckbox();
            return false;
        }

        // ...and to grant all required usage privileges to others
        if (false === $db->isGrantable($this->databaseUsagePrivileges)) {
            $this->error(sprintf(
                $this->translate(
                    'The provided credentials cannot be used to grant all required privileges to the login "%s".'
                ),
                $this->config['username']
            ));
            $this->addSkipValidationCheckbox();
            return false;
        }

        return true;
    }

    /**
     * Add a checkbox to the form by which the user can skip the login and privilege validation
     */
    protected function addSkipValidationCheckbox()
    {
        $this->addElement(
            'checkbox',
            'skip_validation',
            array(
                'order'         => 0,
                'required'      => true,
                'label'         => $this->translate('Skip Validation'),
                'description'   => $this->translate(
                    'Check this to not to validate the ability to login and required privileges'
                )
            )
        );
    }
}