Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Piwik: Pass auth token via POST #240

Merged
merged 2 commits into from
Sep 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions piwik/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ gather statistics about the users accessing Indico or specific Indico events.

## Changelog

### 3.3.1

- Pass `token_auth` via POST instead of query string (more secure, and required by modern Matomo versions)

### 3.3

- Support (and require) Python 3.12
Expand Down
9 changes: 5 additions & 4 deletions piwik/indico_piwik/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from wtforms.validators import ValidationError

from indico.web.forms.base import IndicoForm
from indico.web.forms.fields import IndicoPasswordField
from indico.web.forms.widgets import SwitchWidget

from indico_piwik import _
Expand All @@ -19,10 +20,10 @@ class SettingsForm(IndicoForm):
enabled_for_events = BooleanField(_('Track events'), widget=SwitchWidget())
cache_enabled = BooleanField(_('Cache results'), widget=SwitchWidget())
server_url = StringField(_('Piwik server URL'))
server_api_url = StringField(_('Piwik API server URL'),
description=_("Should be pointing to 'index.php'"))
server_token = StringField(_('Piwik API token'),
description=_('Token to access the API. Do not share it!'))
server_api_url = StringField(_('Piwik API server URL'))
server_token = IndicoPasswordField(_('Piwik API token'),
toggle=True,
description=_('Token to access the API. Do not share it!'))
site_id_general = StringField(_('Global statistics ID'),
description=_('Piwik site ID for global statistics'))
site_id_events = StringField(_('Event statistics ID'),
Expand Down
18 changes: 7 additions & 11 deletions piwik/indico_piwik/piwik.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,31 +38,27 @@ def call(self, default_response=None, **query_params):
:param default_response: Return value in case the query fails
:param query_params: Dictionary with the parameters of the query
"""
query_url = self.get_query_url(**query_params)
return self._perform_call(query_url, default_response)
return self._perform_call(self.api_url, self.get_query(query_params), default_response)

def get_query(self, query_params=None):
"""Return a query string"""
if query_params is None:
query_params = {}
query = ''
query = {}
query_params['idSite'] = self.site_id
if self.api_token is not None:
query_params['token_auth'] = self.api_token
for key, value in query_params.items():
if isinstance(value, list):
value = ','.join(value)
query += f'{key}={value}&'
return query[:-1]
query[key] = value
return query

def get_query_url(self, **query_params):
"""Return the url for a Piwik API query"""
return f'{self.api_url}?{self.get_query(query_params)}'

def _perform_call(self, query_url, default_response=None, timeout=10):
def _perform_call(self, query_url, query_params, default_response=None, timeout=10):
"""Returns the raw results from the API"""
payload = self.get_query(query_params)
try:
response = requests.get(query_url, timeout=timeout)
response = requests.post(query_url, data=payload, timeout=timeout)
except TimeoutError:
current_plugin.logger.warning('Timeout contacting Piwik server')
return default_response
Expand Down
21 changes: 6 additions & 15 deletions piwik/indico_piwik/queries/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@
# see the LICENSE file for more details.

import json
from datetime import timedelta
from functools import reduce

from flask_pluginengine import current_plugin

from indico.util.date_time import format_human_timedelta


def get_json_from_remote_server(func, **kwargs):
"""
Expand Down Expand Up @@ -37,18 +40,6 @@ def reduce_json(data):
return reduce(lambda x, y: int(x) + int(y), list(data.values()))


def stringify_seconds(seconds=0):
"""
Takes time as a value of seconds and deduces the delta in human-readable
HHh MMm SSs format.
"""
seconds = int(seconds)
minutes = seconds / 60

h = m = s = 0
if seconds > 0:
s = seconds % 60
m = minutes % 60
h = minutes / 60

return f'{h}h {m}m {s}s'
def stringify_seconds(seconds):
"""Format seconds in a compact HHh MMm SSs format."""
return format_human_timedelta(timedelta(seconds=seconds), narrow=True)
2 changes: 1 addition & 1 deletion piwik/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = 'indico-plugin-piwik'
description = 'Piwik integration for global and event-specific statistics in Indico'
readme = 'README.md'
version = '3.3'
version = '3.3.1'
license = 'MIT'
authors = [{ name = 'Indico Team', email = '[email protected]' }]
classifiers = [
Expand Down
Loading