"Fossies" - the Fresh Open Source Software Archive

Member "LinOTP-release-2.11/linotpd/src/linotp/tests/integration/linotp_selenium_helper/token_view.py" (12 Nov 2019, 9151 Bytes) of package /linux/misc/LinOTP-release-2.11.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file.

    1 # -*- coding: utf-8 -*-
    2 #
    3 #    LinOTP - the open source solution for two factor authentication
    4 #    Copyright (C) 2010 - 2019 KeyIdentity GmbH
    5 #
    6 #    This file is part of LinOTP server.
    7 #
    8 #    This program is free software: you can redistribute it and/or
    9 #    modify it under the terms of the GNU Affero General Public
   10 #    License, version 3, as published by the Free Software Foundation.
   11 #
   12 #    This program is distributed in the hope that it will be useful,
   13 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
   14 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   15 #    GNU Affero General Public License for more details.
   16 #
   17 #    You should have received a copy of the
   18 #               GNU Affero General Public License
   19 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
   20 #
   21 #
   22 #    E-mail: linotp@keyidentity.com
   23 #    Contact: www.linotp.org
   24 #    Support: www.keyidentity.com
   25 #
   26 """Contains TokenView class"""
   27 
   28 import logging
   29 
   30 from selenium.webdriver.support.ui import WebDriverWait
   31 from selenium.webdriver.common.by import By
   32 from selenium.webdriver.support import expected_conditions as EC
   33 
   34 from selenium.webdriver.support.select import Select
   35 from manage_elements import ManageTab, ManageDialog
   36 from helper import fill_form_element, find_by_id
   37 
   38 logger = logging.getLogger(__name__)
   39 
   40 
   41 class TokenViewException(Exception):
   42     pass
   43 
   44 
   45 class TokenView(ManageTab):
   46     """Represents the 'Token View' tab in the LinOTP WebUI"""
   47 
   48     TAB_INDEX = 1
   49 
   50     token_lines_css = "#token_table tr td:first-child div"
   51     delete_button_id = 'button_delete'
   52     token_table_css = 'table#token_table'
   53 
   54     delete_confirm_dialog = None
   55     "Dialog box shown when tokens are deleted"
   56 
   57     def __init__(self, manage_ui):
   58         super(TokenView, self).__init__(manage_ui)
   59         self.delete_confirm_dialog = ManageDialog(
   60             manage_ui, 'dialog_delete_token')
   61 
   62     def open(self):
   63         """Select the 'Token View' tab"""
   64         self.open_tab()
   65 
   66         # If the '100' in the items-per-page combobox is
   67         # already selected,
   68         # chrome browser ignores the 're-selection' of '100', and
   69         # does not fire a change event.
   70         # That is fine, because if there are pre-selected items
   71         # in e.g. the token list view, the selection is lost.
   72         # BUT firefox fires an event even if the '100' is already
   73         # selected.
   74         # To avoid loosing selected items, we check if the '100'
   75         # is selected.
   76 
   77         select = Select(self.driver.find_element_by_name("rp"))
   78         if(select.first_selected_option.text.strip() != '100'):
   79             # Show 100 tokens in view
   80             self.driver.find_element_by_css_selector(
   81                 "option[value=\"100\"]").click()
   82 
   83         self.wait_for_grid_loading()
   84 
   85     def _get_status_text(self):
   86         # Information text about number of tokens shown
   87         stat_css = self.flexigrid_css + " span.pPageStat"
   88         e = self.find_by_css(stat_css)
   89         return e.text
   90 
   91     def _get_token_list(self):
   92         "Open list and return all tokens shown in the view"
   93         self.open()
   94 
   95         # In order to avoid long timeouts if the token list is empty, check how
   96         # many are shown
   97         text = self._get_status_text()
   98 
   99         if text == "No items":
  100             return []
  101 
  102         e = self.driver.find_elements_by_css_selector(self.token_lines_css)
  103         return e
  104 
  105     def select_all_tokens(self):
  106         tokens = self._get_token_list()
  107 
  108         selected_tokens = self.get_selected_tokens()
  109 
  110         for t in tokens:
  111             if t.text not in selected_tokens:
  112                 t.click()
  113 
  114     def _delete_selected_tokens(self):
  115         tokens_before = [t.text for t in self._get_token_list()]
  116         if not len(tokens_before):
  117             return
  118 
  119         find_by_id(self.driver, self.delete_button_id).click()
  120 
  121         delete_dialog = self.delete_confirm_dialog
  122 
  123         # The delete confirm dialog will open now
  124         delete_dialog.check_title("Delete selected tokens?")
  125 
  126         t = delete_dialog.get_text()
  127         assert t.startswith(
  128             r"The following tokens will be permanently deleted")
  129 
  130         delete_dialog.click_button('button_delete_delete')
  131 
  132         self.manage.wait_for_waiting_finished()  # Wait for delete API call
  133         self.wait_for_grid_loading()  # Wait for flexigrid to refresh
  134 
  135         tokens_after = [t.text for t in self._get_token_list()]
  136 
  137         if len(tokens_before) <= len(tokens_after):
  138             logging.warn("Number of tokens did not reduce as expected. from=%s to=%s",
  139                          tokens_before, tokens_after)
  140             assert len(tokens_before) > len(tokens_after), \
  141                 "The token list should be shorter. Before:%s After:%s" % (
  142                     len(tokens_before), len(tokens_after))
  143 
  144     def clear_tokens_via_api(self):
  145         """
  146         Get all tokens via API call
  147         and delete all by token serial.
  148         """
  149 
  150         # Get the tokens in json format
  151         json_response = self.manage.admin_api_call("admin/show")
  152 
  153         tokens = json_response["result"]["value"]["data"]
  154         if(tokens):
  155             for curr_token in tokens:
  156                 self.manage.admin_api_call("admin/remove",
  157                                            {'serial': curr_token['LinOtp.TokenSerialnumber']})
  158 
  159     def delete_all_tokens(self):
  160         self.open()
  161         self.select_all_tokens()
  162         self._delete_selected_tokens()
  163 
  164     def get_selected_tokens(self):
  165         """
  166         Retrieve a list of currently selected token serials in the UI
  167         """
  168         selected_tokens = find_by_id(self.driver, "selected_tokens").text
  169 
  170         return selected_tokens.split(', ')
  171 
  172     def token_click(self, token_serial):
  173         """
  174         Click on the given token. This toggles its selected state.
  175         """
  176         token_serials = self._get_token_list()
  177 
  178         for token in token_serials:
  179             if token.text == token_serial:
  180                 token.click()
  181                 return
  182 
  183     def select_token(self, token_serial):
  184         """Selects (clicks on) a token in the WebUI. This function does not reload
  185            the page (because otherwise the selection would be lost) neither before
  186            nor after the selection.
  187 
  188            If the token is already selected, this does nothing
  189         """
  190         if token_serial not in self.get_selected_tokens():
  191             self.token_click(token_serial)
  192 
  193     def deselect_token(self, token_serial):
  194         """
  195         Deselect a token if it is already selected
  196         """
  197         if token_serial in self.get_selected_tokens():
  198             self.token_click(token_serial)
  199 
  200     def delete_token(self, token_serial):
  201         self.select_token(token_serial)
  202         self._delete_selected_tokens()
  203 
  204     def assign_token(self, token_serial, pin):
  205         driver = self.driver
  206 
  207         self.select_token(token_serial)
  208 
  209         assign_id = "button_assign"
  210 
  211         WebDriverWait(self.driver, 4).until(
  212             EC.element_to_be_clickable((By.ID, assign_id))
  213         )
  214 
  215         driver.find_element_by_id(assign_id).click()
  216 
  217         self.wait_for_waiting_finished()
  218         fill_form_element(driver, "pin1", pin)
  219         fill_form_element(driver, "pin2", pin)
  220         driver.find_element_by_id("button_setpin_setpin").click()
  221         self.wait_for_waiting_finished()  # Wait for delete API call
  222 
  223     def get_token_info(self, token_serial):
  224         """
  225         Extracts the token info from the WebUI and returns it as a dictionary.
  226         """
  227         keys_with_subtable = ['LinOtp.TokenInfo', 'LinOtp.RealmNames']
  228         self.select_token(token_serial)
  229         self.driver.find_element_by_id("button_tokeninfo").click()
  230         token_info = {}
  231         rows = self.driver.find_elements_by_css_selector(
  232             "#dialog_token_info > table >tbody > tr")
  233 
  234         # Some rows do not contain all elements
  235         self.testcase.disableImplicitWait()
  236 
  237         for row in rows:
  238             tds = row.find_elements_by_css_selector("td.tokeninfoOuterTable")
  239             key = tds[0].text
  240             value_element = tds[1]
  241             if key in keys_with_subtable:
  242                 inner_rows = value_element.find_elements_by_css_selector(
  243                     'table.tokeninfoInnerTable tr')
  244                 if key == 'LinOtp.RealmNames':
  245                     token_info[key] = []
  246                 else:
  247                     token_info[key] = {}
  248                 for inner_row in inner_rows:
  249                     inner_tds = inner_row.find_elements_by_css_selector(
  250                         "td.tokeninfoInnerTable")
  251                     if key == 'LinOtp.RealmNames':
  252                         inner_value = inner_tds[0].text
  253                         token_info[key].append(inner_value)
  254                     else:
  255                         inner_key = inner_tds[0].text
  256                         inner_value = inner_tds[1].text
  257                         token_info[key][inner_key] = inner_value
  258             else:
  259                 token_info[key] = value_element.text
  260         self.testcase.enableImplicitWait()
  261 
  262         self.driver.find_element_by_id("button_ti_close").click()
  263         return token_info