Added filterable to summary and histogram controllers
[ninja.git] / application / controllers / user.php
blobd40fe3449b2ce17d46ee02c7d05515e2b22c6d89
1 <?php defined('SYSPATH') OR die('No direct access allowed.');
2 /**
3 * User controller
4 * Requires authentication
6 * op5, and the op5 logo are trademarks, servicemarks, registered servicemarks
7 * or registered trademarks of op5 AB.
8 * All other trademarks, servicemarks, registered trademarks, and registered
9 * servicemarks mentioned herein may be the property of their respective owner(s).
10 * The information contained herein is provided AS IS with NO WARRANTY OF ANY
11 * KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY, AND FITNESS FOR A
12 * PARTICULAR PURPOSE.
14 class User_Controller extends Authenticated_Controller {
15 # form field types
16 private static $var_types = array(
17 'pagination.default.items_per_page' => 'int',
18 'pagination.paging_step' => 'int',
19 'keycommands.activated' => 'bool',
20 'keycommands.search' => 'string',
21 'keycommands.pause' => 'string',
22 'keycommands.forward' => 'string',
23 'keycommands.back' => 'string',
24 'checks.show_passive_as_active' => 'bool',
25 'config.current_skin' => 'select',
26 'config.use_popups' => 'bool',
27 'config.popup_delay' => 'int',
28 'config.page_refresh_rate' => 'int',
29 'config.listview_refresh_rate' => 'int',
30 'nagdefault.sticky' => 'bool',
31 'nagdefault.persistent' => 'bool',
32 'nagdefault.comment' => 'string',
33 'nagdefault.services-too' => 'bool',
34 'nagdefault.force' => 'bool',
35 'nagdefault.duration' => 'int',
36 'nagdefault.fixed' => 'bool',
37 'nagdefault.notes_url_target' => 'select',
38 'nagdefault.action_url_target' => 'select'
41 /**
42 * Default method
43 * Enable user to edit some GUI settings
45 public function index()
47 $updated = $this->input->get('updated', false);
48 $title = _('User Settings');
49 $this->template->title = $title;
51 $this->template->disable_refresh = true;
52 $this->template->content = $this->add_view('user/settings');
54 $template = $this->template->content;
56 # check if user is an admin
57 $is_admin = Auth::instance()->authorized_for('access_rights');
58 $template->is_admin = $is_admin;
60 $this->template->content->widgets = $this->widgets;
62 $available_setting_sections = array(
63 _('Pagination') => 'pagination',
64 _('Checks') => 'checks',
65 _('Config') => 'config',
66 _('Columns in list view') => 'listview',
67 _('Keyboard Commands') => 'keycommands',
68 _('URL Targets') => 'url_target',
69 _('Nagios Defaults') => 'nagdefault'
72 $sub_headings = array(
73 'listview' => array("https://kb.op5.com/x/AwE6", _('Read specification online'))
76 $settings['pagination'] = array(
77 _('Pagination Limit') => array('pagination.default.items_per_page', self::$var_types['pagination.default.items_per_page']),
78 _('Pagination Step') => array('pagination.paging_step', self::$var_types['pagination.paging_step']),
81 $settings['keycommands'] = array(
82 _('Keycommands') => array('keycommands.activated', self::$var_types['keycommands.activated']),
83 _('Search') => array('keycommands.search', self::$var_types['keycommands.search']),
84 _('Pause') => array('keycommands.pause', self::$var_types['keycommands.pause']),
85 _('Paging Forward') => array('keycommands.forward', self::$var_types['keycommands.forward']),
86 _('Paging Back') => array('keycommands.back', self::$var_types['keycommands.back'])
88 $settings['checks'] = array(
89 _('Show Passive as Active') => array('checks.show_passive_as_active', self::$var_types['checks.show_passive_as_active'])
92 $settings['url_target'] = array(
93 _('Notes URL Target') => array('nagdefault.notes_url_target', self::$var_types['nagdefault.notes_url_target'], Kohana::config('nagdefault.available_targets')),
94 _('Action URL Target') => array('nagdefault.action_url_target', self::$var_types['nagdefault.action_url_target'], Kohana::config('nagdefault.available_targets')),
97 $settings['nagdefault'] = array(
98 _('Sticky') => array('nagdefault.sticky', self::$var_types['nagdefault.sticky']),
99 _('Persistent') => array('nagdefault.persistent', self::$var_types['nagdefault.persistent']),
100 _('Force action') => array('nagdefault.force', self::$var_types['nagdefault.force']),
101 _('Perform action for services too') => array('nagdefault.services-too', self::$var_types['nagdefault.services-too']),
102 _('Fixed') => array('nagdefault.fixed', self::$var_types['nagdefault.fixed']),
103 _('Duration (hours)') => array('nagdefault.duration', self::$var_types['nagdefault.duration']),
104 _('Comment') => array('nagdefault.comment', self::$var_types['nagdefault.comment']));
107 $listview_settings = array();
108 foreach(Kohana::config('listview.columns') as $table => $value) {
109 $listview_settings[_('Table '.ucwords($table))] = array('listview.columns.'.$table, 'textarea');
111 $settings['listview'] = $listview_settings;
113 $settings['config'] = false;
114 $available_skins = ninja::get_skins();
115 $settings['config'] = array(
116 _('Global page refresh rate') => array('config.page_refresh_rate', self::$var_types['config.page_refresh_rate']),
117 _('List view refresh rate') => array('config.listview_refresh_rate', self::$var_types['config.listview_refresh_rate']),
118 _('Current Skin') => array('config.current_skin', self::$var_types['config.current_skin'], $available_skins)
121 $current_values = false;
122 if (!empty($available_setting_sections)) {
123 foreach ($available_setting_sections as $str => $key) {
124 if (!isset($settings[$key])) {
125 continue;
127 foreach ($settings[$key] as $discard => $cfgkey) {
128 if (is_array($cfgkey[0])) {
129 continue;
131 $current_val = Ninja_setting_Model::fetch_page_setting($cfgkey[0], '*');
132 if (is_object($current_val) && count($current_val)) {
133 $current_values[$cfgkey[0]] = $current_val->setting;
134 } else {
135 $current_values[$cfgkey[0]] = Kohana::config($cfgkey[0]);
141 $template->title = _('User settings');
143 $this->template->toolbar = new Toolbar_Controller( _("My Account"), _("Settings") );
144 $root = url::base(FALSE) . 'index.php/';
146 if ( Auth::instance()->authorized_for('access_rights') ) {
147 $this->template->toolbar->info(
148 '<a href="' . $root . 'user/menu_edit' . '" title="' . _( "Edit user menu" ) . '">' . _( "Edit user menu" ) . '</a>'
152 if ( Auth::instance()->authorized_for('own_user_change_password') ) {
153 $this->template->toolbar->info(
154 '<a href="' . $root . 'change_password' . '" title="' . _('Change Password') . '">' . _('Change Password') . '</a>'
158 $template->current_values = $current_values;
159 $template->available_setting_sections = $available_setting_sections;
160 $template->sub_headings = $sub_headings;
161 $template->settings = $settings;
162 $updated_str = false;
164 if ( $updated !== false ) {
165 $updated_str = _('Your settings were successfully saved');
168 $template->updated_str = $updated_str;
172 * Save data from form after some validation
174 public function save()
176 unset($_POST['save_config']);
178 # restore '.' in config keys
179 $restore_string = '_99_';
180 $data = false;
181 foreach ($this->input->post() as $key => $val) {
182 $key = str_replace($restore_string, '.', $key);
183 $data[$key] = $val;
186 # fetch all param type info
187 $type_info = self::$var_types;
189 # Add string to all column types for listview
190 $listview_settings = array();
191 foreach(Kohana::config('listview.columns') as $table => $value) {
192 $type_info['listview.columns.'.$table] = 'string';
195 # make sure we have field type info befor continuing
196 if (empty($type_info)) {
197 die(_('Unable to process user settings since field type info is missing'));
200 # loop through actual settings, validate and save if OK
201 $errors = false;
202 $base_err_str = _('Wrong datatype vaule for field %s. Should be %s - found %s');
203 $empty_str = _('Ignoring %s since no value was found for it.');
204 foreach ($data as $key => $val) {
205 if ($val == '' && $type_info[$key] != 'string') {
206 $errors[$key] = sprintf($empty_str, $key);
208 switch ($type_info[$key]) {
209 case 'int':
210 if (!is_numeric($val)) {
211 $errors[$key] = sprintf($base_err_str, $key, $type_info[$key], $val);
212 } else {
213 $this->_save_value($key, $val);
215 break;
216 case 'bool':
217 if (!is_numeric($val) || ($val != '0' && $val != '1')) {
218 $errors[$key] = sprintf($base_err_str, $key, $type_info[$key], $val);
219 } else {
220 $this->_save_value($key, $val);
222 break;
223 case 'select': case 'string':
224 if (strstr($key, 'keycommand')) {
225 $val = str_replace(' ', '', $val);
227 # no validation for these types yet
228 $this->_save_value($key, $val);
229 break;
230 default:
231 $errors[$key] = sprintf(_('Found no type information for %s so skipping it'), $key);
235 if (!empty($errors)) {
236 $title = _('User Settings');
237 $this->template->title = $title;
239 $this->template->disable_refresh = true;
240 $this->template->content = $this->add_view('user/error');
242 $template = $this->template->content;
244 $this->template->content->widgets = $this->widgets;
245 $template->errors = $errors;
246 } else {
247 return url::redirect('user/index?updated=true');
253 * Save a config key => value pair to db
254 * and session for current user.
256 public function _save_value($key=false, $val=false, $page='*')
258 # save to db
259 Ninja_setting_Model::save_page_setting($key, $page, $val);
261 # save to session
262 $page_val = '';
263 if ($page != '' && !empty($page)) {
264 $page_val = '.'.$page;
266 Session::instance()->set($key.$page_val, $val);
271 * Translated helptexts for this controller
273 public static function _helptexts($id)
275 $keyboard_help = '<br />'._("Possible Modifier keys are Alt, Shift, Ctrl + any key.
276 Modifier keys should be entered in alphabetical order. Add a combination of keys
277 with a + sign between like 'Alt+Shift-f' without any spaces. All keys are case insensitive.");
279 $parts = explode('.',$id);
280 if($parts[0] == 'listview') {
281 return ListView_Controller::_helptexts($id);
283 # Tag unfinished helptexts with @@@HELPTEXT:<key> to make it
284 # easier to find those later
285 $helptexts = array(
286 'pagination.default.items_per_page' => _('Set number of items shown on each page. Defaults to 100.'),
287 'pagination.paging_step' => _('This value is used to generate drop-down for nr of items per page to show. Defaults to 100.'),
288 'checks.show_passive_as_active' => _('This setting affects if to show passive checks as active in the GUI'),
289 'config.page_refresh_rate' => _('Seconds between each automatic page reload (0 disables)'),
290 'config.listview_refresh_rate' => _("Tables including status data ('list views') automatically updates their content. This value indicates seconds between each list view reload (0 disables)"),
291 'config.current_skin' => _('Select the skin to use in the GUI. Affects colors and images.'),
292 'keycommands.activated' => _('Switch keyboard commands ON or OFF. Default is OFF'),
293 'keycommands.search' => _('Keyboard command to set focus to search field. Defaults to Alt+Shift+f.').' '.$keyboard_help,
294 'keycommands.pause' => _('Keyboard command to pause/unpause page refresh. Defaults to Alt+Shift+p.').' '.$keyboard_help,
295 'keycommands.forward' => _('Keyboard command to move forward in a paginated result (except search results). Defaults to Alt+Shift+right.').' '.$keyboard_help,
296 'keycommands.back' => _('Keyboard command to move back in a paginated result (except search results). Defaults to Alt+Shift+left.').' '.$keyboard_help,
297 'edit_menu' => _('Edit menu item visibility for limited users.'),
298 'nagdefault.notes_url_target' => _('This option determines the name of the frame target that notes URLs should be displayed in.'),
299 'nagdefault.action_url_target' => _('This option determines the name of the frame target that action URLs should be displayed in.'),
300 'nagdefault.sticky' => _('Configure the default value for the nagios "sticky" command option'),
301 'nagdefault.persistent' => _('Configure the default value for the nagios "persistent" command option'),
302 'nagdefault.force' => _('Configure the default value for the nagios "force" command option'),
303 'nagdefault.services-too' => _('Configure the default value for the nagios "services-too" command option'),
304 'nagdefault.fixed' => _('Configure the default value for the nagios "fixed" command option'),
305 'nagdefault.duration' => _('Configure the default value for the nagios "duration" command option'),
306 'nagdefault.comment' => _('Configure the default value for the nagios "comment" command option'),
308 if (array_key_exists($id, $helptexts)) {
309 echo $helptexts[$id];
311 else
312 echo sprintf(_("This helptext ('%s') is not translated yet"), $id);
316 * Remove menu item by index
317 * Both section string ['about', 'monitoring', etc]
318 * and item string ['portal', 'manual', 'support', etc] are required.
319 * As a consequence, all menu items has to be explicitly removed before removing the section
321 public function menu_remove(&$menu_links=false, &$menu_items=false, $section_str=false, $group=false, $item_str=false, $save=true)
323 if (empty($menu_links) || empty($menu_items) || empty($section_str)) {
324 return false;
327 if (is_array($section_str)) {
328 if ($save === true) {
329 $config = Op5Config::instance();
330 $ninja_menu = $config->getConfig('ninja_menu');
331 $ninja_menu[$group] = $section_str;
332 $config->setConfig('ninja_menu', $ninja_menu);
335 # we have to make recursive calls
336 foreach ($section_str as $section => $items) {
337 foreach ($items as $item) {
338 $this->menu_remove($menu_links, $menu_items, $section, $item, $group);
341 } else {
342 if (empty($item_str) && isset($menu_links[$menu_items['section_'.$section_str]])
343 && empty($menu_links[$menu_items['section_'.$section_str]])) {
344 # remove the section
345 unset($menu_links[$menu_items['section_'.$section_str]]);
346 } elseif (isset($menu_items[$item_str]) && !empty($item_str) && isset($menu_links[$menu_items['section_'.$section_str]][$menu_items[$item_str]])) {
347 unset($menu_links[$menu_items['section_'.$section_str]][$menu_items[$item_str]]);
354 * Edit menu items
355 * Show form for editing menu items
357 public function menu_edit()
359 if(!Auth::instance()->authorized_for('access_rights')) {
360 // @todo add "you're not authed" flash message
361 //_("You don't have access to this page. Only visible to administrators.");
362 return url::redirect(Router::$controller.'/index');
364 $groups = Auth::get_groups_without_rights(array('access_rights'));
365 $selected_group = $this->input->get('usergroup', false);
366 if($selected_group && !isset($groups[$selected_group])) {
367 return url::redirect(Router::$controller.'/menu_edit');
369 $this->template->disable_refresh = true;
371 $this->template->content = $this->add_view('user/edit_menu');
372 $this->template->js[] = $this->add_path('user/js/user.js');
373 $content = $this->template->content;
375 $content->select_user_message = _("Select the user below to edit the menu for.");
376 $content->description = _("Check the menu items that the should not be visible to the selected user.");
378 $content->groups = $groups;
380 $remove_items = false;
381 $all_items = false;
382 if ($selected_group) {
383 include(APPPATH.'views/menu/menu.php');
384 $config = Op5Config::instance()->getConfig('ninja_menu');
385 if(isset($config[$selected_group])) {
386 $remove_items = $config[$selected_group];
389 // disallowing manually giving someone the right to access nacoma,
390 // it's really controlled by system_information (an access right)
391 unset($menu_base['Configuration']['Configure'], $menu_items['configure']);
392 $all_items = $menu_base;
394 $content->menu_base = $menu_base;
395 $content->menu_items = $menu_items;
396 $content->sections = $sections;
397 $content->menu = $menu;
400 $content->selected_group = $selected_group;
402 $content->remove_items = $remove_items;
403 $content->all_items = $all_items;
405 $this->template->toolbar = new Toolbar_Controller( _("My Account"), _("Edit user menu") );
407 $root = url::base(FALSE) . 'index.php/';
409 $this->template->toolbar->info(
410 '<a href="' . $root . 'user" title="' . _( "Account Settings" ) . '">' . _( "Account Settings" ) . '</a>'
413 if ( Auth::instance()->authorized_for('own_user_change_password') ) {
414 $this->template->toolbar->info(
415 '<a href="' . $root . 'change_password' . '" title="' . _('Change Password') . '">' . _('Change Password') . '</a>'
419 # protected menu items
420 $untouchable_items = array('my_account');
421 $content->untouchable_items = $untouchable_items;
425 * Update menu - save removed items to db
426 * and redirect to menu setup
428 public function menu_update()
430 if(!Auth::instance()->authorized_for('access_rights')) {
431 // @todo add "you're not authed" flash message
432 //_("You don't have access to this page. Only visible to administrators.");
433 return url::redirect(Router::$controller.'/index');
435 $group = $this->input->post('group', false);
436 $remove_items = $this->input->post('remove_items', false);
437 if($_SERVER['REQUEST_METHOD'] != 'POST' || !$group) {
438 return url::redirect(Router::$controller.'/menu_edit');
441 include(APPPATH.'views/menu/menu.php');
443 $all_items = $menu_base;
444 if ($remove_items) {
445 $this->menu_remove($menu_base, $menu_items, $remove_items, $group);
446 } else {
447 $config = Op5Config::instance();
448 $ninja_menu = $config->getConfig('ninja_menu');
449 if(isset($ninja_menu[$group])) {
450 unset($ninja_menu[$group]);
452 $config->setConfig('ninja_menu', $ninja_menu);
455 return url::redirect(Router::$controller."/menu_edit?usergroup=$group");