diff --git a/plugins/kolab_2fa/lib/Kolab2FA/Storage/RcubeUser.php b/plugins/kolab_2fa/lib/Kolab2FA/Storage/RcubeUser.php index 6a4cfd4a..254f47a7 100644 --- a/plugins/kolab_2fa/lib/Kolab2FA/Storage/RcubeUser.php +++ b/plugins/kolab_2fa/lib/Kolab2FA/Storage/RcubeUser.php @@ -1,194 +1,195 @@ * * Copyright (C) 2015, Kolab Systems AG * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ namespace Kolab2FA\Storage; use rcmail; use rcube_user; class RcubeUser extends Base { // sefault config protected $config = [ 'keymap' => [], ]; private $cache = []; private $user; public function init(array $config) { parent::init($config); $rcmail = rcmail::get_instance(); $this->config['hostname'] = $rcmail->user->ID ? $rcmail->user->data['mail_host'] : $_SESSION['hostname']; } /** * List/set methods activated for this user */ public function enumerate() { if ($factors = $this->get_factors()) { return array_keys(array_filter($factors, function ($prop) { return !empty($prop['active']); })); } return []; } /** * Read data for the given key */ public function read($key) { if (!array_key_exists($key, $this->cache)) { $factors = $this->get_factors(); $this->log(LOG_DEBUG, "RcubeUser::read({$key})"); $this->cache[$key] = $factors[$key] ?? null; } return $this->cache[$key]; } /** * Save data for the given key */ public function write($key, $value) { $this->log(LOG_DEBUG, "RcubeUser::write({$key}) " . @json_encode($value)); if ($user = $this->get_user($this->username)) { $this->cache[$key] = $value; $factors = $this->get_factors(); $factors[$key] = $value; - $pkey = $this->key2property('blob'); - $save_data = [$pkey => $factors]; $update_index = false; // remove entry if ($value === null) { unset($factors[$key]); $update_index = true; } // remove non-active entries elseif (!empty($value['active'])) { $factors = array_filter($factors, function ($prop) { return !empty($prop['active']); }); $update_index = true; } + $pkey = $this->key2property('blob'); + $save_data = [$pkey => $factors]; + // update the index of active factors if ($update_index) { $save_data[$this->key2property('factors')] = array_keys( array_filter($factors, function ($prop) { return !empty($prop['active']); }) ); } $success = $user->save_prefs($save_data, true); if (!$success) { $this->log(LOG_WARNING, sprintf('Failed to save prefs for user %s', $this->username)); } return $success; } return false; } /** * Remove the data stored for the given key */ public function remove($key) { return $this->write($key, null); } /** * Set username to store data for */ public function set_username($username) { parent::set_username($username); // reset cached values $this->cache = []; $this->user = null; } /** * Helper method to get a rcube_user instance for storing prefs */ private function get_user($username) { // use global instance if we have a valid Roundcube session $rcmail = rcmail::get_instance(); if ($rcmail->user->ID && $rcmail->user->get_username() == $username) { return $rcmail->user; } if (!$this->user) { $this->user = rcube_user::query($username, $this->config['hostname']); } if (!$this->user) { $this->log(LOG_WARNING, sprintf('No user record found for %s @ %s', $username, $this->config['hostname'])); } return $this->user; } /** * */ private function get_factors() { if ($user = $this->get_user($this->username)) { $prefs = $user->get_prefs(); return (array) ($prefs[$this->key2property('blob')] ?? []); } return null; } /** * */ private function key2property($key) { // map key to configured property name if (is_array($this->config['keymap']) && isset($this->config['keymap'][$key])) { return $this->config['keymap'][$key]; } // default return 'kolab_2fa_' . $key; } }