Add report action
This commit is contained in:
parent
86ec2858a5
commit
67b599ce1a
|
@ -49,7 +49,6 @@ jobs:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: Install requirements
|
- name: Install requirements
|
||||||
run: |
|
run: |
|
||||||
pip install -r requirements.txt
|
|
||||||
pip install -r dev-requirements.txt
|
pip install -r dev-requirements.txt
|
||||||
pip install -e .
|
pip install -e .
|
||||||
# Replace default path to CKAN core config file with the one on the container
|
# Replace default path to CKAN core config file with the one on the container
|
||||||
|
|
|
@ -11,9 +11,13 @@ groups:
|
||||||
|
|
||||||
- key: googleanalytics.account
|
- key: googleanalytics.account
|
||||||
|
|
||||||
|
- key: googleanalytics.profile_id
|
||||||
|
|
||||||
- key: googleanalytics.domain
|
- key: googleanalytics.domain
|
||||||
default: auto
|
default: auto
|
||||||
|
|
||||||
|
- key: googleanalytics.credentials.path
|
||||||
|
|
||||||
- key: googleanalytics.fields
|
- key: googleanalytics.fields
|
||||||
default: "{}"
|
default: "{}"
|
||||||
|
|
||||||
|
|
|
@ -1,44 +1,35 @@
|
||||||
import httplib2
|
|
||||||
from apiclient.discovery import build
|
from apiclient.discovery import build
|
||||||
from oauth2client.service_account import ServiceAccountCredentials
|
from oauth2client.service_account import ServiceAccountCredentials
|
||||||
|
|
||||||
from ckanext.googleanalytics import utils
|
from . import utils
|
||||||
|
|
||||||
|
|
||||||
def _prepare_credentials(credentials_filename):
|
|
||||||
"""
|
|
||||||
Either returns the user's oauth credentials or uses the credentials
|
|
||||||
file to generate a token (by forcing the user to login in the browser)
|
|
||||||
"""
|
|
||||||
scope = ["https://www.googleapis.com/auth/analytics.readonly"]
|
|
||||||
credentials = ServiceAccountCredentials.from_json_keyfile_name(
|
|
||||||
credentials_filename, scopes=scope
|
|
||||||
)
|
|
||||||
return credentials
|
|
||||||
|
|
||||||
|
|
||||||
def init_service(credentials_file):
|
def init_service(credentials_file):
|
||||||
"""
|
"""Get a service that communicates to a Google API."""
|
||||||
Given a file containing the user's oauth token (and another with
|
scope = ["https://www.googleapis.com/auth/analytics.readonly"]
|
||||||
credentials in case we need to generate the token) will return a
|
credentials = ServiceAccountCredentials.from_json_keyfile_name(
|
||||||
service object representing the analytics API.
|
credentials_file, scopes=scope
|
||||||
"""
|
)
|
||||||
http = httplib2.Http()
|
|
||||||
|
|
||||||
credentials = _prepare_credentials(credentials_file)
|
return build("analytics", "v3", credentials=credentials)
|
||||||
http = credentials.authorize(http) # authorize the http object
|
|
||||||
|
|
||||||
return build("analytics", "v3", http=http)
|
|
||||||
|
|
||||||
|
|
||||||
def get_profile_id(service):
|
def get_profile_id(service):
|
||||||
"""
|
"""Get static profile ID or fetch one from the service.
|
||||||
|
|
||||||
Get the profile ID for this user and the service specified by the
|
Get the profile ID for this user and the service specified by the
|
||||||
'googleanalytics.id' configuration option. This function iterates
|
'googleanalytics.id' configuration option. This function iterates
|
||||||
over all of the accounts available to the user who invoked the
|
over all of the accounts available to the user who invoked the
|
||||||
service to find one where the account name matches (in case the
|
service to find one where the account name matches (in case the
|
||||||
user has several).
|
user has several).
|
||||||
|
|
||||||
|
If not user configured, the first account is used
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
profile_id = utils.config_profile_id()
|
||||||
|
if profile_id:
|
||||||
|
return profile_id
|
||||||
|
|
||||||
accounts = service.management().accounts().list().execute()
|
accounts = service.management().accounts().list().execute()
|
||||||
|
|
||||||
if not accounts.get("items"):
|
if not accounts.get("items"):
|
||||||
|
@ -46,14 +37,9 @@ def get_profile_id(service):
|
||||||
accountName = utils.config_account()
|
accountName = utils.config_account()
|
||||||
webPropertyId = utils.config_id()
|
webPropertyId = utils.config_id()
|
||||||
for acc in accounts.get("items"):
|
for acc in accounts.get("items"):
|
||||||
if acc.get("name") == accountName:
|
if not accountName or acc.get("name") == accountName:
|
||||||
accountId = acc.get("id")
|
accountId = acc.get("id")
|
||||||
|
|
||||||
# TODO: check, whether next line is doing something useful.
|
|
||||||
service.management().webproperties().list(
|
|
||||||
accountId=accountId
|
|
||||||
).execute()
|
|
||||||
|
|
||||||
profiles = (
|
profiles = (
|
||||||
service.management()
|
service.management()
|
||||||
.profiles()
|
.profiles()
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
header_code = """
|
|
||||||
<script type="text/javascript">
|
|
||||||
var _gaq = _gaq || [];
|
|
||||||
_gaq.push(['_setAccount', '%s']);
|
|
||||||
_gaq.push(['_setDomainName', '%s']);
|
|
||||||
_gaq.push(['_trackPageview']);
|
|
||||||
(function() {
|
|
||||||
var ga = document.createElement('script');
|
|
||||||
ga.type = 'text/javascript'; ga.async = true;
|
|
||||||
ga.src = ('https:' == document.location.protocol ?
|
|
||||||
'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
|
|
||||||
var s = document.getElementsByTagName('script')[0];
|
|
||||||
s.parentNode.insertBefore(ga, s);
|
|
||||||
})();
|
|
||||||
</script>
|
|
||||||
"""
|
|
||||||
|
|
||||||
footer_code = """
|
|
||||||
<script type="text/javascript" src="%s"></script>
|
|
||||||
"""
|
|
||||||
|
|
||||||
download_style = """
|
|
||||||
<style type="text/css">
|
|
||||||
span.downloads-count {
|
|
||||||
font-size: 0.9em;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
"""
|
|
|
@ -4,19 +4,22 @@ import ckan.plugins.toolkit as tk
|
||||||
from ckan.logic import validate
|
from ckan.logic import validate
|
||||||
|
|
||||||
from . import schema
|
from . import schema
|
||||||
|
from .. import utils
|
||||||
from ..model import PackageStats, ResourceStats
|
from ..model import PackageStats, ResourceStats
|
||||||
|
from ..ga_auth import init_service, get_profile_id
|
||||||
|
|
||||||
|
|
||||||
def get_actions():
|
def get_actions():
|
||||||
return dict(
|
return dict(
|
||||||
googleanalytics_package_stats_show=googleanalytics_package_stats_show,
|
googleanalytics_package_stats_show=package_stats_show,
|
||||||
googleanalytics_resource_stats_show=googleanalytics_resource_stats_show
|
googleanalytics_resource_stats_show=resource_stats_show,
|
||||||
|
googleanalytics_event_report=event_report,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@validate(schema.googleanalytics_package_stats_show)
|
@validate(schema.package_stats_show)
|
||||||
@tk.side_effect_free
|
@tk.side_effect_free
|
||||||
def googleanalytics_package_stats_show(context, data_dict):
|
def package_stats_show(context, data_dict):
|
||||||
tk.check_access("googleanalytics_package_stats_show", context, data_dict)
|
tk.check_access("googleanalytics_package_stats_show", context, data_dict)
|
||||||
rec = (
|
rec = (
|
||||||
context["session"]
|
context["session"]
|
||||||
|
@ -31,9 +34,9 @@ def googleanalytics_package_stats_show(context, data_dict):
|
||||||
return rec.for_json(context)
|
return rec.for_json(context)
|
||||||
|
|
||||||
|
|
||||||
@validate(schema.googleanalytics_resource_stats_show)
|
@validate(schema.resource_stats_show)
|
||||||
@tk.side_effect_free
|
@tk.side_effect_free
|
||||||
def googleanalytics_resource_stats_show(context, data_dict):
|
def resource_stats_show(context, data_dict):
|
||||||
tk.check_access("googleanalytics_resource_stats_show", context, data_dict)
|
tk.check_access("googleanalytics_resource_stats_show", context, data_dict)
|
||||||
rec = (
|
rec = (
|
||||||
context["session"]
|
context["session"]
|
||||||
|
@ -46,3 +49,35 @@ def googleanalytics_resource_stats_show(context, data_dict):
|
||||||
raise tk.ObjectNotFound()
|
raise tk.ObjectNotFound()
|
||||||
|
|
||||||
return rec.for_json(context)
|
return rec.for_json(context)
|
||||||
|
|
||||||
|
|
||||||
|
@validate(schema.event_report)
|
||||||
|
@tk.side_effect_free
|
||||||
|
def event_report(context, data_dict):
|
||||||
|
tk.check_access("sysadmin", context, data_dict)
|
||||||
|
|
||||||
|
se = init_service(utils.config_credentials())
|
||||||
|
filters = "ga:eventAction=={action};ga:eventCategory=={category}".format(
|
||||||
|
action=data_dict["action"], category=data_dict["category"]
|
||||||
|
)
|
||||||
|
if "label" in data_dict:
|
||||||
|
filters += ";ga:eventLabel=={label}".format(label=data_dict["label"])
|
||||||
|
|
||||||
|
report = (
|
||||||
|
se.data()
|
||||||
|
.ga()
|
||||||
|
.get(
|
||||||
|
ids="ga:{id}".format(id=get_profile_id(se)),
|
||||||
|
dimensions=",".join(data_dict["dimensions"]),
|
||||||
|
metrics=",".join(data_dict["metrics"]),
|
||||||
|
start_date=data_dict["start_date"].date().isoformat(),
|
||||||
|
end_date=data_dict["end_date"].date().isoformat(),
|
||||||
|
filters=filters,
|
||||||
|
)
|
||||||
|
.execute()
|
||||||
|
)
|
||||||
|
|
||||||
|
return {
|
||||||
|
"headers": [h["name"] for h in report["columnHeaders"]],
|
||||||
|
"rows": report["rows"],
|
||||||
|
}
|
||||||
|
|
|
@ -5,14 +5,14 @@ from ckan.authz import is_authorized
|
||||||
|
|
||||||
def get_auth():
|
def get_auth():
|
||||||
return dict(
|
return dict(
|
||||||
googleanalytics_package_stats_show=googleanalytics_package_stats_show,
|
googleanalytics_package_stats_show=package_stats_show,
|
||||||
googleanalytics_resource_stats_show=googleanalytics_resource_stats_show
|
googleanalytics_resource_stats_show=resource_stats_show,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def googleanalytics_package_stats_show(context, data_dict):
|
def package_stats_show(context, data_dict):
|
||||||
return {"success": is_authorized("package_show", context, data_dict)}
|
return {"success": is_authorized("package_show", context, data_dict)}
|
||||||
|
|
||||||
|
|
||||||
def googleanalytics_resource_stats_show(context, data_dict):
|
def resource_stats_show(context, data_dict):
|
||||||
return {"success": is_authorized("resource_show", context, data_dict)}
|
return {"success": is_authorized("resource_show", context, data_dict)}
|
||||||
|
|
|
@ -2,10 +2,31 @@ from ckan.logic.schema import validator_args
|
||||||
|
|
||||||
|
|
||||||
@validator_args
|
@validator_args
|
||||||
def googleanalytics_package_stats_show(not_empty):
|
def package_stats_show(not_empty):
|
||||||
return {"id": [not_empty]}
|
return {"id": [not_empty]}
|
||||||
|
|
||||||
|
|
||||||
@validator_args
|
@validator_args
|
||||||
def googleanalytics_resource_stats_show(not_empty):
|
def resource_stats_show(not_empty):
|
||||||
return {"id": [not_empty]}
|
return {"id": [not_empty]}
|
||||||
|
|
||||||
|
|
||||||
|
@validator_args
|
||||||
|
def event_report(
|
||||||
|
not_empty, isodate, ignore_missing, json_list_or_string, default
|
||||||
|
):
|
||||||
|
return {
|
||||||
|
"start_date": [not_empty, isodate],
|
||||||
|
"end_date": [not_empty, isodate],
|
||||||
|
"category": [not_empty],
|
||||||
|
"action": [not_empty],
|
||||||
|
"label": [ignore_missing, not_empty],
|
||||||
|
"dimensions": [
|
||||||
|
default("ga:eventCategory,ga:eventAction,ga:eventLabel"),
|
||||||
|
json_list_or_string,
|
||||||
|
],
|
||||||
|
"metrics": [
|
||||||
|
default("ga:totalEvents,ga:uniqueEvents,ga:eventValue"),
|
||||||
|
json_list_or_string,
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
|
@ -14,6 +14,14 @@ def config_account():
|
||||||
return tk.config.get("googleanalytics.account")
|
return tk.config.get("googleanalytics.account")
|
||||||
|
|
||||||
|
|
||||||
|
def config_profile_id():
|
||||||
|
return tk.config.get("googleanalytics.profile_id")
|
||||||
|
|
||||||
|
|
||||||
|
def config_credentials():
|
||||||
|
return tk.config.get("googleanalytics.credentials.path")
|
||||||
|
|
||||||
|
|
||||||
def config_domain():
|
def config_domain():
|
||||||
return tk.config.get("googleanalytics.domain", "auto")
|
return tk.config.get("googleanalytics.domain", "auto")
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[metadata]
|
[metadata]
|
||||||
name = ckanext-googleanalytics
|
name = ckanext-googleanalytics
|
||||||
version = 2.0.8
|
version = 2.1.0
|
||||||
description = Add GA tracking and reporting to CKAN instance
|
description = Add GA tracking and reporting to CKAN instance
|
||||||
long_description = file: README.md
|
long_description = file: README.md
|
||||||
long_description_content_type = text/markdown
|
long_description_content_type = text/markdown
|
||||||
|
@ -23,6 +23,7 @@ keywords =
|
||||||
# python_requires = >= 3.7
|
# python_requires = >= 3.7
|
||||||
install_requires =
|
install_requires =
|
||||||
ckantoolkit
|
ckantoolkit
|
||||||
|
google-api-python-client
|
||||||
|
|
||||||
packages = find:
|
packages = find:
|
||||||
namespace_packages = ckanext
|
namespace_packages = ckanext
|
||||||
|
|
Loading…
Reference in New Issue