"Fossies" - the Fresh Open Source Software Archive

Member "LinOTP-release-2.11/linotpd/src/linotp/lib/reporting.py" (12 Nov 2019, 8427 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. For more information about "reporting.py" see the Fossies "Dox" file reference documentation.

    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 import json
   27 import logging
   28 
   29 from linotp.model import Reporting
   30 from linotp.model.meta import Session
   31 
   32 from linotp.lib.context import request_context
   33 from linotp.lib.monitoring import MonitorHandler
   34 from linotp.lib.policy import check_token_reporting
   35 
   36 from sqlalchemy import (and_, or_)
   37 from sqlalchemy import func
   38 
   39 log = logging.getLogger(__name__)
   40 
   41 
   42 def token_reporting(event, tokenrealms):
   43     """
   44     log token events into reporting table
   45 
   46     :param event: the event that happened, e.g. init token, delete token
   47     :param tokenrealms: the realm on which the event happened
   48     :return: nothing
   49     """
   50     realms = tokenrealms
   51     if not tokenrealms or len(tokenrealms) == 0:
   52         realms = ['/:no realm:/']
   53     elif not isinstance(tokenrealms, (list, tuple)):
   54         realms = [tokenrealms]
   55 
   56     for realm in realms:
   57         action = check_token_reporting(realm)
   58         mh = MonitorHandler()
   59         counters = mh.token_count(realm, action[:])
   60         for key, val in counters.items():
   61             report = Reporting(
   62                 event=event, realm=realm, parameter=key, count=val)
   63             try:
   64                 Session.add(report)
   65             except Exception as exce:
   66                 log.exception('Error during saving report. Exception was: '
   67                               '%r' % exce)
   68 
   69 
   70 def get_max(realm, status='active'):
   71     """
   72     get the maximum number of tokens (with given status) in a realm in the whole
   73      reporting database;
   74      if no status is given, 'active' is default
   75 
   76     :param realm: (required) the realm in which we are searching
   77     :param status: (default: 'active') the status that the tokens have
   78             defaukt is active as this is relevant for license
   79     :return: maximum number of reported tokens with given status in realm
   80     """
   81 
   82     max = Session.query(
   83         func.max(Reporting.count))\
   84         .filter(and_(Reporting.parameter == status, Reporting.realm == realm))
   85 
   86     result = max.first()[0]
   87 
   88     return result
   89 
   90 
   91 def delete(realms, status, date=None):
   92     """
   93     delete all rows in reporting database before a given date,
   94     filtered by realm and status
   95 
   96     :param realms: the ralm to filter
   97     :param status: the status to filter
   98     :param date: (optional) day until which all rows will be deleted
   99     :type date: string in format: 'yyyy-mm-dd'
  100 
  101     :return: number of deleted rows
  102     """
  103 
  104     if not isinstance(realms, (list, tuple)):
  105         realms = realms.split(',')
  106 
  107     realm_cond = tuple()
  108     for realm in realms:
  109         realm_cond += (or_(Reporting.realm == realm),)
  110 
  111     status_cond = tuple()
  112     for stat in status:
  113         status_cond += (or_(Reporting.parameter == stat),)
  114 
  115     date_cond = tuple()
  116     if date:
  117         date_cond += (and_(Reporting.timestamp < date),)
  118 
  119     conds = (and_(*date_cond), or_(*realm_cond), or_(*status_cond),)
  120 
  121     rows = Session.query(Reporting).filter(*conds)
  122     row_num = rows.count()
  123 
  124     for row in rows:
  125         Session.delete(row)
  126     return row_num
  127 
  128 
  129 class ReportingIterator(object):
  130     """
  131     support a smooth iterating through lines in reporting table
  132     """
  133 
  134     def __init__(self, page=None, psize=None, sort=None, sortdir=None,
  135                  realms=None, status=None, date=None):
  136         """
  137         constructor of Tokeniterator, which gathers all conditions to build
  138         a sqalchemy query - iterator
  139 
  140         :param page:     page number
  141         :type  page:     int
  142         :param psize:    how many entries per page
  143         :type  psize:    int
  144         :param sort:     sort field definition
  145         :type  sort:     string
  146         :param sortdir:  sort direction: ascending or descending
  147         :type  sortdir:  string
  148         :param realms:   reports from which realms will be shown
  149         :type realms:    list
  150         :param status:   filter reports by status like active, unassigned
  151         :type status:    list
  152         :param date:     only show entries newer than date
  153         :type date:      strin gin format 'yyyy-mm-dd'
  154 
  155         :return: - nothing / None
  156         """
  157         self.page = 1
  158         self.pages = 1
  159         if not isinstance(realms, (list, tuple)):
  160             realms = realms.split(',')
  161         if not isinstance(status, (list, tuple)):
  162             status = status.split(',')
  163 
  164         realm_cond = tuple()
  165         for realm in realms:
  166             realm_cond += (or_(Reporting.realm == realm),)
  167 
  168         status_cond = tuple()
  169         for stat in status:
  170             status_cond += (or_(Reporting.parameter == stat),)
  171 
  172         date_cond = tuple()
  173         if date:
  174             date_cond += (and_(Reporting.timestamp >= date),)
  175 
  176         conds = (and_(*date_cond), or_(*realm_cond), or_(*status_cond),)
  177 
  178         if sort is None:
  179             order = Reporting.timestamp
  180         elif sort == 'event':
  181             order = Reporting.event
  182         elif sort == 'realm':
  183             order = Reporting.realm
  184         elif sort == 'parameter':
  185             order = Reporting.parameter
  186         elif sort == 'value':
  187             order = Reporting.value
  188         elif sort == 'count':
  189             order = Reporting.count
  190         elif sort == 'detail':
  191             order = Reporting.detail
  192         elif sort == 'description':
  193             order = Reporting.description
  194         elif sort == 'session':
  195             order = Reporting.session
  196         else:
  197             order = Reporting.timestamp
  198 
  199         #  care for the result sort order
  200         if sortdir is not None and sortdir == "desc":
  201             order = order.desc()
  202         else:
  203             order = order.asc()
  204 
  205         # query database for all reports
  206         self.reports = Session.query(Reporting).filter(*conds).order_by(
  207             order).distinct()
  208         self.report_num = self.reports.count()
  209         self.pagesize = self.report_num
  210 
  211         #  care for the result pageing
  212         if page is not None:
  213             try:
  214                 if psize is None:
  215                     pagesize = \
  216                         int(request_context.get('Config').get('pagesize', 50))
  217                 else:
  218                     pagesize = int(psize)
  219             except Exception as exce:
  220                 log.debug('Reporting: Problem with pagesize detected. '
  221                           'Exception was: %r' % exce)
  222                 pagesize = 20
  223 
  224             try:
  225                 the_page = int(page) - 1
  226             except Exception as exce:
  227                 log.debug('Reporting: Problem with page detected. '
  228                           'Exception was %r' % exce)
  229                 the_page = 0
  230 
  231             if the_page < 0:
  232                 the_page = 0
  233 
  234             start = the_page * pagesize
  235             stop = (the_page + 1) * pagesize
  236 
  237             self.page = the_page + 1
  238             fpages = float(self.report_num) / float(pagesize)
  239             self.pages = int(fpages)
  240             if fpages - self.pages > 0:
  241                 self.pages += 1
  242             self.pagesize = pagesize
  243             self.reports = self.reports.slice(start, stop)
  244 
  245     def getResultSetInfo(self):
  246         res_set = {"pages": self.pages,
  247                    "pagesize": self.pagesize,
  248                    "report_rows": self.report_num,
  249                    "page": self.page
  250                    }
  251         return res_set
  252 
  253     def iterate_reports(self):
  254         try:
  255             for rep in self.reports:
  256                 desc = json.dumps(rep.get_vars())
  257                 yield desc
  258 
  259         except Exception as exx:
  260             log.exception("Reporting: Problem during iteration. "
  261                           "Exception was %r" % exx)