Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
// This file is part of Moodle - http://moodle.org/
3
//
4
// Moodle is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// Moodle is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16
 
17
namespace tool_mfa\local;
18
 
19
use tool_mfa\local\factor\object_factor_base;
20
 
21
defined('MOODLE_INTERNAL') || die();
22
 
23
require_once($CFG->libdir.'/ddllib.php');
24
require_once($CFG->libdir.'/xmlize.php');
25
require_once($CFG->libdir.'/messagelib.php');
26
 
27
/**
28
 * Admin setting for MFA.
29
 *
30
 * @package     tool_mfa
31
 * @author      Mikhail Golenkov <golenkovm@gmail.com>
32
 * @copyright   Catalyst IT
33
 * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
34
 */
35
class admin_setting_managemfa extends \admin_setting {
36
 
37
    /**
38
     * Calls parent::__construct with specific arguments
39
     */
40
    public function __construct() {
41
        $this->nosave = true;
42
        parent::__construct('mfaui', get_string('mfasettings', 'tool_mfa'), '', '');
43
    }
44
 
45
    /**
46
     * Always returns true
47
     *
48
     * @return bool
49
     */
50
    public function get_setting(): bool {
51
        return true;
52
    }
53
 
54
    /**
55
     * Always returns '' and doesn't write anything
56
     *
57
     * @param mixed $data
58
     * @return string Always returns ''
59
     */
60
    public function write_setting($data): string {
61
        return '';
62
    }
63
 
64
    /**
65
     * Returns XHTML to display Manage MFA admin page.
66
     *
67
     * @param mixed $data Unused
68
     * @param string $query
69
     *
70
     * @return string highlight
71
     * @throws \coding_exception
72
     * @throws \moodle_exception
73
     */
74
    public function output_html($data, $query=''): string {
75
        global $OUTPUT;
76
 
77
        $return = $OUTPUT->box_start('generalbox');
78
        $return .= $this->define_manage_mfa_table();
79
        $return .= $OUTPUT->box_end();
80
 
81
        $return .= $OUTPUT->heading(get_string('settings:combinations', 'tool_mfa'), 3);
82
        $return .= $OUTPUT->box_start('generalbox');
83
        $return .= $this->define_factor_combinations_table();
84
        $return .= $OUTPUT->box_end();
85
 
86
        return highlight($query, $return);
87
    }
88
 
89
    /**
90
     * Defines main table with configurable factors.
91
     *
92
     * @return string HTML code
93
     * @throws \coding_exception
94
     * @throws \moodle_exception
95
     */
96
    public function define_manage_mfa_table() {
97
        global $OUTPUT;
98
        $sesskey = sesskey();
99
 
100
        $txt = get_strings(['enable', 'disable', 'moveup', 'movedown', 'order', 'settings']);
101
        $txt->factor = get_string('factor', 'tool_mfa');
102
        $txt->weight = get_string('weight', 'tool_mfa');
103
        $txt->setup = get_string('setuprequired', 'tool_mfa');
104
        $txt->input = get_string('inputrequired', 'tool_mfa');
105
 
106
        $table = new \html_table();
107
        $table->id = 'managemfatable';
108
        $table->attributes['class'] = 'admintable generaltable';
109
        $table->head  = [
110
            $txt->factor,
111
            $txt->enable,
112
            $txt->order,
113
            $txt->weight,
114
            $txt->settings,
115
            $txt->setup,
116
            $txt->input,
117
        ];
118
        $table->colclasses = ['leftalign', 'centeralign', 'centeralign', 'centeralign', 'centeralign'];
119
        $table->data  = [];
120
 
121
        $factors = \tool_mfa\plugininfo\factor::get_factors();
122
        $enabledfactors = \tool_mfa\plugininfo\factor::get_enabled_factors();
123
        $order = 1;
124
 
125
        foreach ($factors as $factor) {
126
            $settingsparams = ['section' => 'factor_'.$factor->name];
127
            $settingsurl = new \moodle_url('settings.php', $settingsparams);
128
            $settingslink = \html_writer::link($settingsurl, $txt->settings);
129
 
130
            if ($factor->is_enabled()) {
131
                $hideshowparams = ['action' => 'disable', 'factor' => $factor->name, 'sesskey' => $sesskey];
132
                $hideshowurl = new \moodle_url('tool/mfa/index.php', $hideshowparams);
133
                $hideshowlink = \html_writer::link($hideshowurl, $OUTPUT->pix_icon('t/hide', $txt->disable));
134
                $class = '';
135
 
136
                if ($order > 1) {
137
                    $upparams = ['action' => 'up', 'factor' => $factor->name, 'sesskey' => $sesskey];
138
                    $upurl = new \moodle_url('tool/mfa/index.php', $upparams);
139
                    $uplink = \html_writer::link($upurl, $OUTPUT->pix_icon('t/up', $txt->moveup));
140
                } else {
141
                    $uplink = \html_writer::link('', $uplink = $OUTPUT->spacer(['style' => 'margin-right: .5rem']));
142
                }
143
 
144
                if ($order < count($enabledfactors)) {
145
                    $downparams = ['action' => 'down', 'factor' => $factor->name, 'sesskey' => $sesskey];
146
                    $downurl = new \moodle_url('tool/mfa/index.php', $downparams);
147
                    $downlink = \html_writer::link($downurl, $OUTPUT->pix_icon('t/down', $txt->movedown));
148
                } else {
149
                    $downlink = '';
150
                }
151
                $updownlink = $uplink.$downlink;
152
                $order++;
153
            } else {
154
                $hideshowparams = ['action' => 'enable', 'factor' => $factor->name, 'sesskey' => $sesskey];
155
                $hideshowurl = new \moodle_url('tool/mfa/index.php', $hideshowparams);
156
                $hideshowlink = \html_writer::link($hideshowurl, $OUTPUT->pix_icon('t/show', $txt->enable));
157
                $class = 'dimmed_text';
158
                $updownlink = '';
159
            }
160
 
161
            $hassetup = $factor->has_setup() ? get_string('yes') : get_string('no');
162
            $hasinput = $factor->has_input() ? get_string('yes') : get_string('no');
163
 
164
            $rowarray = [
165
                $factor->get_display_name(),
166
                $hideshowlink,
167
                $updownlink,
168
                $factor->get_weight(),
169
                $settingslink,
170
                $hassetup,
171
                $hasinput,
172
            ];
173
            $row = new \html_table_row($rowarray);
174
            $row->attributes['class'] = $class;
175
 
176
            $table->data[] = $row;
177
        }
178
 
179
        return \html_writer::table($table);
180
    }
181
 
182
    /**
183
     * Defines supplementary table that shows available combinations of factors enough for successful authentication.
184
     *
185
     * @return string HTML code
186
     */
187
    public function define_factor_combinations_table() {
188
        global $OUTPUT;
189
 
190
        $factors = \tool_mfa\plugininfo\factor::get_enabled_factors();
191
        $combinations = $this->get_factor_combinations($factors, 0, count($factors) - 1);
192
 
193
        if (empty($combinations)) {
194
            return $OUTPUT->notification(get_string('error:notenoughfactors', 'tool_mfa'), 'notifyproblem');
195
        }
196
 
197
        $txt = get_strings(['combination', 'totalweight'], 'tool_mfa');
198
        $table = new \html_table();
199
        $table->id = 'managemfatable';
200
        $table->attributes['class'] = 'admintable generaltable table table-bordered';
201
        $table->head  = [$txt->combination, $txt->totalweight];
202
        $table->colclasses = ['leftalign', 'centeralign'];
203
        $table->data  = [];
204
 
205
        $factorstringconnector = get_string('connector', 'tool_mfa');
206
        foreach ($combinations as $combination) {
207
            $factorstrings = array_map(static function(object_factor_base $factor): string {
208
                return $factor->get_summary_condition() . ' <sup>' . $factor->get_weight() . '</sup>';
209
            }, $combination['combination']);
210
 
211
            $string = implode(" {$factorstringconnector} ", $factorstrings);
212
            $table->data[] = new \html_table_row([$string, $combination['totalweight']]);
213
        }
214
 
215
        return \html_writer::table($table);
216
    }
217
 
218
    /**
219
     * Recursive method to get all possible combinations of given factors.
220
     * Output is filtered by combination total weight (should be greater than 100).
221
     *
222
     * @param array $allfactors initial array of factor objects
223
     * @param int $start start position in initial array
224
     * @param int $end end position in initial array
225
     * @param int $totalweight total weight of combination
226
     * @param array $combination combination candidate
227
     * @param array $result array that includes combination total weight and subarray of factors combination
228
     *
229
     * @return array
230
     */
231
    public function get_factor_combinations($allfactors, $start = 0, $end = 0,
232
        $totalweight = 0, $combination = [], $result = []) {
233
 
234
        if ($totalweight >= 100) {
235
            // Ensure this is a valid combination before appending result.
236
            $valid = true;
237
            foreach ($combination as $factor) {
238
                if (!$factor->check_combination($combination)) {
239
                    $valid = false;
240
                }
241
            }
242
            if ($valid) {
243
                $result[] = ['totalweight' => $totalweight, 'combination' => $combination];
244
            }
245
            return $result;
246
        } else if ($start > $end) {
247
            return $result;
248
        }
249
 
250
        $combinationnext = $combination;
251
        $combinationnext[] = $allfactors[$start];
252
 
253
        $result = $this->get_factor_combinations(
254
            $allfactors,
255
            $start + 1,
256
            $end,
257
            $totalweight + $allfactors[$start]->get_weight(),
258
            $combinationnext,
259
            $result);
260
 
261
        $result = $this->get_factor_combinations(
262
            $allfactors,
263
            $start + 1,
264
            $end,
265
            $totalweight,
266
            $combination,
267
            $result);
268
 
269
        return $result;
270
    }
271
}