From f57cad9ee98b2dd55e6ed1f559f01800771ce2fc Mon Sep 17 00:00:00 2001 From: mutantsan Date: Wed, 20 Nov 2024 13:52:53 +0200 Subject: [PATCH] Deployed 9df26cc with MkDocs version: 1.6.1 --- 404.html | 2 +- assets/_mkdocstrings.css | 26 +- cli/index.html | 267 ++++++- configure/active_repo/index.html | 2 +- configure/async/index.html | 2 +- configure/cloudwatch/index.html | 2 +- configure/ignore/index.html | 2 +- configure/tracking/index.html | 2 +- exporters/basic/index.html | 19 +- exporters/csv/index.html | 27 +- exporters/json/index.html | 15 +- exporters/tsv/index.html | 11 +- exporters/xlsx/index.html | 19 +- index.html | 2 +- install/index.html | 2 +- interfaces/index.html | 7 +- objects.inv | Bin 661 -> 678 bytes repositories/abstract/index.html | 122 +++- repositories/basic/index.html | 2 +- repositories/cloudwatch/index.html | 66 +- repositories/custom/index.html | 34 +- repositories/postgres/index.html | 154 +++- repositories/redis/index.html | 110 ++- repositories/test/index.html | 1048 ---------------------------- search/search_index.json | 2 +- sitemap.xml | 50 +- sitemap.xml.gz | Bin 368 -> 364 bytes usage/index.html | 2 +- utils/index.html | 15 +- validators/index.html | 10 +- 30 files changed, 858 insertions(+), 1164 deletions(-) delete mode 100644 repositories/test/index.html diff --git a/404.html b/404.html index 6461629..f4e979c 100644 --- a/404.html +++ b/404.html @@ -12,7 +12,7 @@ - + diff --git a/assets/_mkdocstrings.css b/assets/_mkdocstrings.css index 85449ec..b500381 100644 --- a/assets/_mkdocstrings.css +++ b/assets/_mkdocstrings.css @@ -26,20 +26,33 @@ float: right; } +/* Parameter headings must be inline, not blocks. */ +.doc-heading-parameter { + display: inline; +} + +/* Prefer space on the right, not the left of parameter permalinks. */ +.doc-heading-parameter .headerlink { + margin-left: 0 !important; + margin-right: 0.2rem; +} + /* Backward-compatibility: docstring section titles in bold. */ .doc-section-title { font-weight: bold; } /* Symbols in Navigation and ToC. */ -:root, +:root, :host, [data-md-color-scheme="default"] { + --doc-symbol-parameter-fg-color: #df50af; --doc-symbol-attribute-fg-color: #953800; --doc-symbol-function-fg-color: #8250df; --doc-symbol-method-fg-color: #8250df; --doc-symbol-class-fg-color: #0550ae; --doc-symbol-module-fg-color: #5cad0f; + --doc-symbol-parameter-bg-color: #df50af1a; --doc-symbol-attribute-bg-color: #9538001a; --doc-symbol-function-bg-color: #8250df1a; --doc-symbol-method-bg-color: #8250df1a; @@ -48,12 +61,14 @@ } [data-md-color-scheme="slate"] { + --doc-symbol-parameter-fg-color: #ffa8cc; --doc-symbol-attribute-fg-color: #ffa657; --doc-symbol-function-fg-color: #d2a8ff; --doc-symbol-method-fg-color: #d2a8ff; --doc-symbol-class-fg-color: #79c0ff; --doc-symbol-module-fg-color: #baff79; + --doc-symbol-parameter-bg-color: #ffa8cc1a; --doc-symbol-attribute-bg-color: #ffa6571a; --doc-symbol-function-bg-color: #d2a8ff1a; --doc-symbol-method-bg-color: #d2a8ff1a; @@ -68,6 +83,15 @@ code.doc-symbol { font-weight: bold; } +code.doc-symbol-parameter { + color: var(--doc-symbol-parameter-fg-color); + background-color: var(--doc-symbol-parameter-bg-color); +} + +code.doc-symbol-parameter::after { + content: "param"; +} + code.doc-symbol-attribute { color: var(--doc-symbol-attribute-fg-color); background-color: var(--doc-symbol-attribute-bg-color); diff --git a/cli/index.html b/cli/index.html index 70e090a..9ff36e8 100644 --- a/cli/index.html +++ b/cli/index.html @@ -18,7 +18,7 @@ - + @@ -435,6 +435,15 @@ + + +
  • + + + remove_events + + +
  • @@ -978,6 +987,15 @@ + + +
  • + + + remove_events + + +
  • @@ -1010,6 +1028,11 @@

    CLI

    + + + + +
    @@ -1043,7 +1066,9 @@

    - exporter_name + + exporter_name +

    The name of the exporter.

    @@ -1057,7 +1082,9 @@

    - start + + start +

    The start date string in %Y-%m-%d format.

    @@ -1071,7 +1098,9 @@

    - end + + end +

    The end date string in %Y-%m-%d format.

    @@ -1085,7 +1114,9 @@

    - config + + config +

    The exporter config in JSON format. See the exporter's @@ -1128,13 +1159,14 @@

    Example

    $ ckan event-audit export-data csv --start=2024-11-11 > report.csv

    -

    $ ckan event-audit export-data json --start=2024-11-11 | jq '[.[] | {id, category, action}]'

    -

    $ ckan event-audit export-data xlsx --start=2024-11-11 --config='{"file_path": "/tmp/test.xlsx"}'

    +

    $ ckan event-audit export-data json --start=2024-11-11 | jq '[.[] | + {id, category, action}]'

    +

    $ ckan event-audit export-data xlsx --start=2024-11-11 + --config='{"file_path": "/tmp/test.xlsx"}'

    Source code in ckanext/event_audit/cli.py -
    + - + - + - + - + - + - + - + + + + + - + - + - + - +
    20
    -21
    +              
    + + + - + - + - + - + - + + - + - + + + - + + + + + + + + - + - + - + - + - + - + - +
    21
     22
     23
     24
    @@ -1184,7 +1216,12 @@ 

    68 69 70 -71

    @event_audit.command()
    +71
    +72
    +73
    +74
    +75
    +76
    @event_audit.command()
     @click.argument("exporter_name", type=str)
     @click.option(
         "--start",
    @@ -1215,10 +1252,15 @@ 

    Example: $ ckan event-audit export-data csv --start=2024-11-11 > report.csv - $ ckan event-audit export-data json --start=2024-11-11 | jq '[.[] | {id, category, action}]' + $ ckan event-audit export-data json --start=2024-11-11 | jq '[.[] | + {id, category, action}]' - $ ckan event-audit export-data xlsx --start=2024-11-11 --config='{"file_path": "/tmp/test.xlsx"}' + $ ckan event-audit export-data xlsx --start=2024-11-11 + --config='{"file_path": "/tmp/test.xlsx"}' """ + start = UTC.localize(start) if start else None + end = UTC.localize(end) if end else None + try: config_dict = json.loads(config or "{}") except json.JSONDecodeError: @@ -1228,9 +1270,8 @@

    exporter = utils.get_exporter(exporter_name)(**config_dict) except TypeError as e: return click.secho(f"Invalid exporter config: {config}. Error: {e}", fg="red") - - if not exporter: - return click.secho(f"Unknown exporter: {exporter_name}", fg="red") + except ValueError as e: + return click.secho(e, fg="red") if start and end and start > end: return click.secho("Start date must be before the end date.", fg="red") @@ -1242,6 +1283,202 @@

    +
    + + +

    + remove_events(repository, start, end) + +

    + + +
    + +

    Remove events from the repository by time range.

    + + + + + + + + + + + + + + + + + + + + + + + +
    PARAMETERDESCRIPTION
    + repository + +
    +

    The repository name. If not provided, the +active repository will be used.

    +
    +

    + + TYPE: + str | None + +

    +
    + start + +
    +

    The start date string in %Y-%m-%d format.

    +
    +

    + + TYPE: + str + +

    +
    + end + +
    +

    The end date string in %Y-%m-%d format.

    +
    +

    + + TYPE: + str | None + +

    +
    + + +
    + Example +

    $ ckan event-audit remove-events --start=2024-11-11 --end=2024-11-12

    +
    +
    + Source code in ckanext/event_audit/cli.py +
     79
    + 80
    + 81
    + 82
    + 83
    + 84
    + 85
    + 86
    + 87
    + 88
    + 89
    + 90
    + 91
    + 92
    + 93
    + 94
    + 95
    + 96
    + 97
    + 98
    + 99
    +100
    +101
    +102
    +103
    +104
    +105
    +106
    +107
    +108
    +109
    +110
    +111
    +112
    +113
    +114
    +115
    +116
    +117
    +118
    +119
    +120
    +121
    +122
    +123
    +124
    +125
    +126
    +127
    +128
    +129
    +130
    +131
    +132
    +133
    @event_audit.command()
    +@click.option("--repository", required=False, help="The repository name")
    +@click.option(
    +    "--start",
    +    required=False,
    +    type=click.DateTime(formats=["%Y-%m-%d"]),
    +    help="ISO format start date",
    +)
    +@click.option(
    +    "--end",
    +    required=False,
    +    type=click.DateTime(formats=["%Y-%m-%d"]),
    +    help="ISO format end date",
    +)
    +def remove_events(repository: str | None, start: dt | None, end: dt | None):
    +    """Remove events from the repository by time range.
    +
    +    Args:
    +        repository (str | None): The repository name. If not provided, the
    +            active repository will be used.
    +        start (str): The start date string in %Y-%m-%d format.
    +        end (str | None): The end date string in %Y-%m-%d format.
    +
    +    Example:
    +        $ ckan event-audit remove-events --start=2024-11-11 --end=2024-11-12
    +    """
    +    start = UTC.localize(start) if start else None
    +    end = UTC.localize(end) if end else None
    +
    +    if start and end and start > end:
    +        return click.secho("Start date must be before the end date.", fg="red")
    +
    +    try:
    +        repo = utils.get_repo(repository) if repository else utils.get_active_repo()
    +    except ValueError:
    +        return click.secho(f"Unknown repository: {repository}", fg="red")
    +
    +    if not (start or end) and not isinstance(repo, repositories.RemoveAll):
    +        return click.secho(
    +            f"Repository {repository} does not support removing events.", fg="red"
    +        )
    +
    +    if not isinstance(repo, repositories.RemoveFiltered):
    +        if start or end:
    +            return click.secho(
    +                (
    +                    f"Repository {repository} does not support removing events "
    +                    "by time range. "
    +                    "Please remove the --start and --end flags to delete all events."
    +                ),
    +                fg="red",
    +            )
    +        return repo.remove_all_events()
    +
    +    return repo.remove_events(types.Filters(time_from=start, time_to=end))
    +
    +
    +
    + +
    + diff --git a/configure/active_repo/index.html b/configure/active_repo/index.html index 724fe31..b956019 100644 --- a/configure/active_repo/index.html +++ b/configure/active_repo/index.html @@ -18,7 +18,7 @@ - + diff --git a/configure/async/index.html b/configure/async/index.html index 0bfed6c..fc4973e 100644 --- a/configure/async/index.html +++ b/configure/async/index.html @@ -18,7 +18,7 @@ - + diff --git a/configure/cloudwatch/index.html b/configure/cloudwatch/index.html index 3ebd6ce..4fc19f5 100644 --- a/configure/cloudwatch/index.html +++ b/configure/cloudwatch/index.html @@ -18,7 +18,7 @@ - + diff --git a/configure/ignore/index.html b/configure/ignore/index.html index fe0b690..5bd96a5 100644 --- a/configure/ignore/index.html +++ b/configure/ignore/index.html @@ -18,7 +18,7 @@ - + diff --git a/configure/tracking/index.html b/configure/tracking/index.html index a897844..5ff5c4d 100644 --- a/configure/tracking/index.html +++ b/configure/tracking/index.html @@ -18,7 +18,7 @@ - + diff --git a/exporters/basic/index.html b/exporters/basic/index.html index 7dacf9b..b6fc540 100644 --- a/exporters/basic/index.html +++ b/exporters/basic/index.html @@ -18,7 +18,7 @@ - + @@ -1058,6 +1058,11 @@

    Base exporter class

    + + + + +
    @@ -1097,7 +1102,9 @@

    -

    events + events +

    events to export

    @@ -1169,7 +1176,9 @@

    -

    filters + filters +

    search filters.

    @@ -1183,7 +1192,9 @@

    -

    repo_name + repo_name +

    name of the repo to use. Defaults to None.

    diff --git a/exporters/csv/index.html b/exporters/csv/index.html index 7ef35c4..8331edc 100644 --- a/exporters/csv/index.html +++ b/exporters/csv/index.html @@ -18,7 +18,7 @@ - + @@ -1032,6 +1032,11 @@

    CSV exporter

    + + + + +
    @@ -1065,7 +1070,9 @@

    delimiter + delimiter +

    delimiter. Defaults to ",".

    @@ -1083,7 +1090,9 @@

    quotechar + quotechar +

    quote character. Defaults to '"'.

    @@ -1101,7 +1110,9 @@

    quoting + quoting +

    quoting. Defaults to QUOTE_ALL.

    @@ -1119,7 +1130,9 @@

    ignore_fields + ignore_fields +

    fields to ignore. By @@ -1167,7 +1180,9 @@

    events + events +

    events to export.

    diff --git a/exporters/json/index.html b/exporters/json/index.html index 8c78e88..f6ba974 100644 --- a/exporters/json/index.html +++ b/exporters/json/index.html @@ -18,7 +18,7 @@ - + @@ -1034,6 +1034,11 @@

    JSON exporter

    + + + + +
    @@ -1067,7 +1072,9 @@

    -

    stringify + stringify +

    whether to return a string or a dict. By @@ -1115,7 +1122,9 @@

    events + events +

    events to export.

    diff --git a/exporters/tsv/index.html b/exporters/tsv/index.html index b802166..36a4929 100644 --- a/exporters/tsv/index.html +++ b/exporters/tsv/index.html @@ -18,7 +18,7 @@ - + @@ -1014,6 +1014,11 @@

    TSV exporter

    + + + + +
    @@ -1047,7 +1052,9 @@

    ignore_fields + ignore_fields +

    fields to ignore. By diff --git a/exporters/xlsx/index.html b/exporters/xlsx/index.html index 62c8f98..7363a4f 100644 --- a/exporters/xlsx/index.html +++ b/exporters/xlsx/index.html @@ -18,7 +18,7 @@ - + @@ -1032,6 +1032,11 @@

    XLSX exporter

    + + + + +
    @@ -1065,7 +1070,9 @@

    -

    file_path + file_path +

    path to the file or BytesIO object to @@ -1080,7 +1087,9 @@

    -

    ignore_fields + ignore_fields +

    fields to ignore. By @@ -1128,7 +1137,9 @@

    events + events +

    events to export.

    diff --git a/index.html b/index.html index aabb571..6cad978 100644 --- a/index.html +++ b/index.html @@ -16,7 +16,7 @@ - + diff --git a/install/index.html b/install/index.html index 32cab3c..b98b588 100644 --- a/install/index.html +++ b/install/index.html @@ -18,7 +18,7 @@ - + diff --git a/interfaces/index.html b/interfaces/index.html index 6c70059..cab4aa2 100644 --- a/interfaces/index.html +++ b/interfaces/index.html @@ -18,7 +18,7 @@ - + @@ -1098,6 +1098,11 @@

    IEventAudit

    + + + + +
    diff --git a/objects.inv b/objects.inv index 0ce56bdbc1bf126039fc6dd9ffe485ce7c151c82..b6247f314634e6d7759a79fff8cb0c8badb1068e 100644 GIT binary patch delta 554 zcmV+_0@eMM1*Qd%hksbXZW|#Ky!R_Cwbx?x+FKOm(5h;yxN37ln0d4D?VN~;ZBq3~12b92*> z+r`h0l~R;wDZR+(04aO}-UrzJ7$wQ)#ka5V>+_H_%7G;g5nAW?M@j|l>z?<*?8(EI z#X~%!hon&scs@^v(haT{2SYyH`Tm>GtznJEjnF52kM;;lr_``j2CdSM*OQvRxILsg zflH`0a?&t??tcnVu9l%Ytjqazi|l9bIQ1o2=LVsd>if>8+ieNE7n^+wowF7-Qej!6 zsLoa*rwYh_HPldC=Wqp{zpiuYticxd;x#1OKtYN2bz?%5FWKo!I+09CI~I(kTuBKB z_Hs%)jkbKM~jSE#*J7)QBa_gJFeDm4GcJ>*2CVzG0xKb?oR>-Cpbw6ZNONw!B z)yZv6XfYw=*)${L9@~ delta 537 zcmV+!0_Odu1(gMmhkut(Z`&Xk#_#(Sk=E;odflz6de}6rQ!{P7A%fpzZ%ZHr?4;j* zKwKwvlNuc8B|^aS{CNLh$IyVZl+_hl!UYo8u9dd5VwO$T&tDg{o9#5E2361;?3A}0+K z=$;13)bx)kwm;Mo}HjL{19G zry6P~&e=TzcNkNUvjkf_7SE7u1qBfrR;mHYgeae~mQ^}y7L27_NeMgma-@w$TRxrx zN{;Gqq3UYGEdNKY{qV0JzIxyseZ9Ow?LE$fMc>wJ#DA!Jn~j!qy>e4OF3f~0myH>D z`J#DlXqVazezk)!ZTezz1}myTGjNhxGav6GLQ81J47A8b%uC8qEe#bKa_4`?^m>qw zLPWLrc>AQzJ{waokc2)S4~cBw6M)*HFrlFCp9i{hcu~(M?0Hw(FcfSqp!;St<1NCe bQ{^YVRT2kvsnLdtwwXFv*aL_EXRZMxKb{RR diff --git a/repositories/abstract/index.html b/repositories/abstract/index.html index ff81d41..1522a0f 100644 --- a/repositories/abstract/index.html +++ b/repositories/abstract/index.html @@ -18,7 +18,7 @@ - + @@ -904,6 +904,15 @@ + + +
  • + + + remove_events + + +
  • @@ -1127,6 +1136,15 @@ +
  • + +
  • + + + remove_events + + +
  • @@ -1187,6 +1205,11 @@

    Abstract

    + + + + +
    @@ -1237,7 +1260,9 @@

    -

  • event_data + event_data +

    event data.

    @@ -1304,7 +1329,9 @@

    -

    event + event +

    event to write.

    @@ -1375,7 +1402,9 @@

    -

    filters + filters +

    filters to apply.

    @@ -1422,7 +1451,9 @@

    -

    event_id + event_id +

    event ID.

    @@ -1580,7 +1611,9 @@

    -

    event_id + event_id +

    event ID.

    @@ -1627,6 +1660,75 @@

    +

    + remove_events(filters) + +

    + + +
    + +

    Removes a filtered set of events from the repository.

    + + + + + + + + + + + + + + + +
    PARAMETERDESCRIPTION
    + filters + +
    +

    filters to apply.

    +
    +

    + + TYPE: + Filters + +

    +
    + + + + + + + + + + + + + + + +
    RETURNSDESCRIPTION
    + + Result + + +
    +

    types.Result: result of the operation.

    +
    +
    + +
    + +
    + +
    + +

    test_connection() @@ -1700,7 +1802,9 @@

    -

    event + event +

    event to write.

    @@ -1767,7 +1871,9 @@

    -

    events + events +

    events to write.

    diff --git a/repositories/basic/index.html b/repositories/basic/index.html index 665ef6d..8094c99 100644 --- a/repositories/basic/index.html +++ b/repositories/basic/index.html @@ -18,7 +18,7 @@ - + diff --git a/repositories/cloudwatch/index.html b/repositories/cloudwatch/index.html index dfd8744..2b0880a 100644 --- a/repositories/cloudwatch/index.html +++ b/repositories/cloudwatch/index.html @@ -18,7 +18,7 @@ - + @@ -944,6 +944,15 @@ + + +
  • + + + remove_events + + +
  • @@ -1070,6 +1079,15 @@ +
  • + +
  • + + + remove_events + + +
  • @@ -1122,6 +1140,11 @@

    Cloudwatch repository

    + + + + +
    @@ -1155,7 +1178,9 @@

  • credentials + credentials +

    AWS credentials. @@ -1174,7 +1199,9 @@

    log_group + log_group +

    CloudWatch log group name.

    @@ -1192,7 +1219,9 @@

    log_stream + log_stream +

    CloudWatch log stream name.

    @@ -1239,7 +1268,9 @@

    filters + filters +

    filters to apply.

    @@ -1282,7 +1313,9 @@

    event_id + event_id +

    event ID.

    @@ -1398,6 +1431,23 @@

    +

    + remove_events(filters) + +

    + + +
    + +

    See remove_event method docstring.

    + +
    + +
    + +
    + +

    test_connection() @@ -1463,7 +1513,9 @@

    event + event +

    event to write.

    diff --git a/repositories/custom/index.html b/repositories/custom/index.html index 4f8efd7..044e1ed 100644 --- a/repositories/custom/index.html +++ b/repositories/custom/index.html @@ -16,7 +16,7 @@ - + @@ -981,16 +981,22 @@

    Custom

    def test_connection(self) -> types.Result: return types.Result(success=True)
    -

    In this version, it doesn't implement the remove_event and remove_events methods, but you can implement them in the same way as the other methods. If the repository able to remove one or multiple events, it must inherits from the respective class - RemoveSingle or RemoveAll. For example:

    +

    In this version, it doesn't implement the remove_event, remove_events and remove_all_events methods, but you can implement them in the same way as the other methods. If the repository able to remove one or multiple events, it must inherits from the respective class - RemoveSingle or RemoveAll. For example:

    import os
     
    -from ckanext.event_audit.repositories import AbstractRepository, RemoveSingle, RemoveAll
    +from ckanext.event_audit.repositories import (
    +    AbstractRepository,
    +    RemoveSingle,
    +    RemoveAll,
    +    RemoveFiltered,
    +)
     
    -class FileRepository(AbstractRepository, RemoveSingle, RemoveAll):
    +
    +class FileRepository(AbstractRepository, RemoveSingle, RemoveAll, RemoveFiltered):
         ...
     
         def remove_event(self, event_id: Any) -> types.Result:
    -        with open(self.file_path, 'w') as f:
    +        with open(self.file_path, "w") as f:
                 data = json.load(f)
     
                 if event_id in data:
    @@ -999,9 +1005,25 @@ 

    Custom

    return types.Result(success=True) - return types.Result(success=False, message='Event not found') + return types.Result(success=False, message="Event not found") def remove_events(self, filters: types.Filters) -> types.Result: + with open(self.file_path, "w") as f: + data = json.load(f) + + for event_id, event in data.items(): + if _match_filters(event, filters): + del data[event_id] + + f.write(json.dumps(data)) + + return types.Result(success=True) + + def _match_filters( + self, event: types.EventData, filters: types.Filters + ) -> bool: ... + + def remove_all_events(self, filters: types.Filters) -> types.Result: """Removes the file if exists.""" if os.path.exists(self.file_path): diff --git a/repositories/postgres/index.html b/repositories/postgres/index.html index 83c503c..b176f5d 100644 --- a/repositories/postgres/index.html +++ b/repositories/postgres/index.html @@ -18,7 +18,7 @@ - + @@ -914,6 +914,15 @@ + + +
  • + + + remove_events + + +
  • @@ -1061,6 +1070,15 @@ +
  • + +
  • + + + remove_events + + +
  • @@ -1122,6 +1140,11 @@

    Postgres repository

    + + + + +
    @@ -1155,7 +1178,9 @@

  • filters + filters +

    filters to apply.

    @@ -1171,6 +1196,30 @@

    + + + + + + + + + + + + + + +
    RETURNSDESCRIPTION
    + + List[Event] + + +
    +

    List[types.Event]: list of events.

    +
    +
    +
    @@ -1198,7 +1247,9 @@

    -

    event_id + event_id +

    event ID.

    @@ -1306,7 +1357,9 @@

    event_id + event_id +

    event ID.

    @@ -1320,7 +1373,9 @@

    session + session +

    session to use.

    @@ -1338,7 +1393,9 @@

    defer_commit + defer_commit +

    whether to defer the commit.

    @@ -1389,6 +1446,75 @@

    +

    + remove_events(filters) + +

    + + +
    + +

    Removes a filtered set of events from the repository.

    + + + + + + + + + + + + + + + +
    PARAMETERDESCRIPTION
    + filters + +
    +

    filters to apply.

    +
    +

    + + TYPE: + Filters + +

    +
    + + + + + + + + + + + + + + + +
    RETURNSDESCRIPTION
    + + Result + + +
    +

    types.Result: result of the operation.

    +
    +
    + +
    + +
    + +
    + +

    test_connection() @@ -1454,7 +1580,9 @@

    event + event +

    event to write.

    @@ -1468,7 +1596,9 @@

    session + session +

    session to use.

    @@ -1486,7 +1616,9 @@

    defer_commit + defer_commit +

    whether to defer the commit.

    @@ -1557,7 +1689,9 @@

    events + events +

    events to write.

    diff --git a/repositories/redis/index.html b/repositories/redis/index.html index 9473d70..9f59eb0 100644 --- a/repositories/redis/index.html +++ b/repositories/redis/index.html @@ -18,7 +18,7 @@ - + @@ -893,6 +893,15 @@ + + +
  • + + + remove_events + + +
  • @@ -1052,6 +1061,15 @@ +
  • + +
  • + + + remove_events + + +
  • @@ -1104,6 +1122,11 @@

    Redis repository

    + + + + +
    @@ -1137,7 +1160,9 @@

    -

  • filters + filters +

    filters to apply.

    @@ -1180,7 +1205,9 @@

    -

    event_id + event_id +

    event ID.

    @@ -1264,7 +1291,9 @@

    -

    event_id + event_id +

    event ID.

    @@ -1311,6 +1340,75 @@

    +

    + remove_events(filters) + +

    + + +
    + +

    Removes a filtered set of events from the repository.

    + + + + + + + + + + + + + + + +
    PARAMETERDESCRIPTION
    + filters + +
    +

    filters to apply.

    +
    +

    + + TYPE: + Filters + +

    +
    + + + + + + + + + + + + + + + +
    RETURNSDESCRIPTION
    + + Result + + +
    +

    types.Result: result of the operation.

    +
    +
    + +
    + +
    + +
    + +

    test_connection() @@ -1376,7 +1474,9 @@

    -

    event + event +

    event to write.

    diff --git a/repositories/test/index.html b/repositories/test/index.html deleted file mode 100644 index 4d9c1a7..0000000 --- a/repositories/test/index.html +++ /dev/null @@ -1,1048 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - Test - ckanext-event-audit - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - -
    - - - - - - -
    - - -
    - -
    - - - - - - -
    -
    - - - -
    -
    -
    - - - - - -
    -
    -
    - - - -
    -
    -
    - - - -
    -
    -
    - - - -
    -
    - - - - - - - -

    Test

    - -

    RemoveSingle class

    -

    If repository supports removing single log entries, it should inherit the RemoveSingle class.

    - - -
    - - - - -
    - - -

    Mark the repository as supporting remove single event.

    -

    If the repository supports remove single event, it should inherit from -this class.

    - - -
    - -
    - -
    - - - - -
    - - -

    Mark the repository as supporting remove all events.

    -

    If the repository supports remove all events, it should inherit from -this class.

    - - -
    - -
    - - - - - - - - - - - - - -
    -
    - - - -
    - - - -
    - - - -
    -
    -
    -
    - -
    - - - - - - - - - - \ No newline at end of file diff --git a/search/search_index.json b/search/search_index.json index fef0f8e..325e010 100644 --- a/search/search_index.json +++ b/search/search_index.json @@ -1 +1 @@ -{"config":{"lang":["en"],"separator":"[\\s\\-\\.\\_]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Home","text":""},{"location":"#ckanext-event-audit","title":"ckanext-event-audit","text":"

    This extension will capture and retain a comprehensive record of all changes within a CKAN app.

    "},{"location":"#developer-installation","title":"Developer installation","text":"

    To install ckanext-event-audit for development, activate your CKAN virtualenv and do:

    git clone https://github.com/DataShades/ckanext-event-audit.git\ncd ckanext-event-audit\npip install -e .\npip install -r dev-requirements.txt\n
    "},{"location":"#tests","title":"Tests","text":"

    To run the tests, do:

    pytest --ckan-ini=test.ini\n
    "},{"location":"#license","title":"License","text":"

    AGPL

    "},{"location":"cli/","title":"CLI","text":""},{"location":"cli/#event_audit.cli.export_data","title":"export_data(exporter_name, start, end, config)","text":"

    Export data using the specified exporter.

    PARAMETER DESCRIPTION exporter_name

    The name of the exporter.

    TYPE: str

    start

    The start date string in %Y-%m-%d format.

    TYPE: str

    end

    The end date string in %Y-%m-%d format.

    TYPE: str | None

    config

    The exporter config in JSON format. See the exporter's documentation for args details.

    TYPE: str | None

    RETURNS DESCRIPTION str

    The exported data

    Example

    $ ckan event-audit export-data csv --start=2024-11-11 > report.csv

    $ ckan event-audit export-data json --start=2024-11-11 | jq '[.[] | {id, category, action}]'

    $ ckan event-audit export-data xlsx --start=2024-11-11 --config='{\"file_path\": \"/tmp/test.xlsx\"}'

    Source code in ckanext/event_audit/cli.py
    @event_audit.command()\n@click.argument(\"exporter_name\", type=str)\n@click.option(\n    \"--start\",\n    required=True,\n    type=click.DateTime(formats=[\"%Y-%m-%d\"]),\n    help=\"ISO format start date\",\n)\n@click.option(\n    \"--end\",\n    required=False,\n    type=click.DateTime(formats=[\"%Y-%m-%d\"]),\n    help=\"ISO format end date\",\n)\n@click.option(\"--config\", required=False, type=str, help=\"Custom config in JSON format\")\ndef export_data(exporter_name: str, start: dt, end: dt | None, config: str | None):\n    \"\"\"Export data using the specified exporter.\n\n    Args:\n        exporter_name (str): The name of the exporter.\n        start (str): The start date string in %Y-%m-%d format.\n        end (str | None): The end date string in %Y-%m-%d format.\n        config (str | None): The exporter config in JSON format. See the exporter's\n            documentation for args details.\n\n    Returns:\n        str : The exported data\n\n    Example:\n        $ ckan event-audit export-data csv --start=2024-11-11 > report.csv\n\n        $ ckan event-audit export-data json --start=2024-11-11 | jq '[.[] | {id, category, action}]'\n\n        $ ckan event-audit export-data xlsx --start=2024-11-11 --config='{\"file_path\": \"/tmp/test.xlsx\"}'\n    \"\"\"\n    try:\n        config_dict = json.loads(config or \"{}\")\n    except json.JSONDecodeError:\n        return click.secho(\"Invalid JSON format for config.\")\n\n    try:\n        exporter = utils.get_exporter(exporter_name)(**config_dict)\n    except TypeError as e:\n        return click.secho(f\"Invalid exporter config: {config}. Error: {e}\", fg=\"red\")\n\n    if not exporter:\n        return click.secho(f\"Unknown exporter: {exporter_name}\", fg=\"red\")\n\n    if start and end and start > end:\n        return click.secho(\"Start date must be before the end date.\", fg=\"red\")\n\n    click.echo(exporter.from_filters(types.Filters(time_from=start, time_to=end)))\n
    "},{"location":"install/","title":"Installation","text":""},{"location":"install/#requirements","title":"Requirements","text":"

    Compatibility with core CKAN versions:

    CKAN version Compatible? 2.9 no 2.10 yes 2.11 yes master yes"},{"location":"install/#installation_1","title":"Installation","text":"
    1. Install the extension from PyPI:

      pip install ckanext-event-audit\n

    2. Enable the plugin in your CKAN configuration file (e.g. ckan.ini or production.ini):

      ckan.plugins = ... event_audit ...\n

    3. Run DB migrations:

      ckan db upgrade -p event_audit\n

    4. Configure the extension up to your needs and you're ready to go. See the documentation for more details about the configuration options.

    "},{"location":"interfaces/","title":"Interfaces","text":""},{"location":"interfaces/#ieventaudit","title":"IEventAudit","text":"

    Extend functionality of ckanext-event-audit.

    Example:

    import ckan.plugins as p\n\nfrom ckanext.event_audit.interfaces import IEventAudit\nfrom ckanext.event_audit.repositories import AbstractRepository\nfrom ckanext.event_audit.exporters import AbstractExporter\n\nclass MyPlugin(p.SingletonPlugin):\n    p.implements(IEventAudit, inherit=True)\n\n    def register_repository(self) -> dict[str, type[AbstractRepository]]:\n        return {\n            \"my_repo\": MyRepository,\n        }\n\n    def register_exporter(self) -> dict[str, type[AbstractExporter]]:\n        return {\n            \"my_exporter\": MyExporter,\n        }\n\n    def skip_event(self, event: types.Event) -> bool:\n        if event.category == \"api\" and event.action == \"status_show\":\n            return True\n\n        if event.category == \"model\" and event.action_object == \"Dashboard\":\n            return True\n\n        return False\n

    "},{"location":"interfaces/#event_audit.interfaces.IEventAudit.register_exporter","title":"register_exporter()","text":"

    Return the exporters provided by this plugin.

    Example
    def register_exporter(self):\n    return {\n        \"csv\": CSVExporter,\n    }\n
    RETURNS DESCRIPTION dict[str, type[AbstractExporter]]

    mapping of exporter names to exporter classes

    "},{"location":"interfaces/#event_audit.interfaces.IEventAudit.register_repository","title":"register_repository()","text":"

    Return the repositories provided by this plugin.

    Example
    def register_repository(self):\n    return {\n        \"my_repo\": MyRepository,\n    }\n
    RETURNS DESCRIPTION dict[str, type[AbstractRepository]]

    mapping of repository names to repository classes

    "},{"location":"interfaces/#event_audit.interfaces.IEventAudit.skip_event","title":"skip_event(event)","text":"

    Skip an event.

    This method is called before writing the event to the repository.

    Example
    def skip_event(self, event: types.Event) -> bool:\n    if event.category == \"api\" and event.action == \"status_show\":\n        return True\n\n    if  event.category == \"model\"  and event.action_object == \"Dashboard\":\n        return True\n\n    return False\n
    RETURNS DESCRIPTION bool

    True if the event should be skipped, False otherwise

    "},{"location":"usage/","title":"Usage","text":"

    To use an event audit in your extension, you should get an instance of the repository class. There are two ways to do this:

    1. Using the get_repo function:

      import ckanext.event_audit.utils as utils\n\nrepo = utils.get_active_repo()\n\nevent = repo.build_event({\"category\": \"xxx\", \"action\": \"xxx\"})\n\nrepo.write_event(event)\n

      The get_active_repo function will return an instance of the active repository class that is configured in the CKAN configuration file.

    2. Using the get_repo function with a specific repository:

      import ckanext.event_audit.utils as utils\n\nrepo = utils.get_repo(\"file\")\n\nevent = repo.build_event({\"category\": \"xxx\", \"action\": \"xxx\"})\n\nrepo.write_event(event)\n

      The get_repo function will return an instance of the repository class that is specified in the argument. You can use this method to get a specific repository instance.

    "},{"location":"utils/","title":"Utility Functions","text":""},{"location":"utils/#event_audit.utils.get_active_repo","title":"get_active_repo()","text":"

    Get the active repository.

    The active repository is the one that is currently configured in the extension configuration.

    RETURNS DESCRIPTION AbstractRepository

    The active repository.

    "},{"location":"utils/#event_audit.utils.get_available_exporters","title":"get_available_exporters()","text":"

    Retrieve a dictionary of available exporters.

    This function collects and returns a dictionary where the keys are exporter names (as strings) and the values are the corresponding exporter classes.

    RETURNS DESCRIPTION dict[str, type[AbstractExporter]]

    A dictionary mapping exporter names to their respective exporter classes.

    "},{"location":"utils/#event_audit.utils.get_available_repos","title":"get_available_repos()","text":"

    Retrieve a dictionary of available repositories.

    This function collects and returns a dictionary where the keys are repository names (as strings) and the values are the corresponding repository classes.

    RETURNS DESCRIPTION dict[str, type[AbstractRepository]]

    A dictionary mapping repository names to their respective repository classes.

    "},{"location":"utils/#event_audit.utils.get_exporter","title":"get_exporter(exporter_name)","text":"

    Retrieve an exporter class by name.

    This function retrieves an exporter class by name. If the exporter is not found, a ValueError is raised.

    PARAMETER DESCRIPTION exporter_name

    The name of the exporter to retrieve.

    TYPE: str

    RETURNS DESCRIPTION type[AbstractExporter]

    The exporter class.

    "},{"location":"utils/#event_audit.utils.get_repo","title":"get_repo(repo_name)","text":"

    Retrieve a repository class by name.

    This function retrieves a repository class by name. If the repository is not found, a ValueError is raised.

    PARAMETER DESCRIPTION repo_name

    The name of the repository to retrieve.

    TYPE: str

    RETURNS DESCRIPTION AbstractRepository

    The repository class.

    "},{"location":"utils/#event_audit.utils.test_active_connection","title":"test_active_connection()","text":"

    Test the connection to the active repository.

    When we test the connection, we store the result in the repository object, so we can reuse it later.

    RETURNS DESCRIPTION bool

    whether the connection is active

    "},{"location":"validators/","title":"Validators","text":""},{"location":"validators/#event_audit.logic.validators.audit_repo_exists","title":"audit_repo_exists(value, context)","text":"

    Check if the repository with the given name is registered.

    PARAMETER DESCRIPTION value

    The repository name.

    TYPE: Any

    context

    The CKAN context.

    TYPE: Context

    RETURNS DESCRIPTION Any

    The repository name if it exists.

    TYPE: Any

    RAISES DESCRIPTION Invalid

    If the repository does not exist.

    Source code in ckanext/event_audit/logic/validators.py
    def audit_repo_exists(value: Any, context: Context) -> Any:\n    \"\"\"Check if the repository with the given name is registered.\n\n    Args:\n        value (Any): The repository name.\n        context (Context): The CKAN context.\n\n    Returns:\n        Any: The repository name if it exists.\n\n    Raises:\n        tk.Invalid: If the repository does not exist.\n    \"\"\"\n    if value not in utils.get_available_repos():\n        raise tk.Invalid(f\"Repository `{value}` is not registered\")\n\n    return value\n
    "},{"location":"configure/active_repo/","title":"Active repository","text":"

    The event audit logs are stored in a configurable storages, we call them repositories.

    The default repository is redis, but it can be changed to a different one. To do this, we have to set the following configuration options in the CKAN configuration file:

    ckanext.event_audit.active_repo = postgres\n

    The following repositories are available:

    1. redis - the default repository, stores logs in Redis.
    2. postgres - stores logs in a PostgreSQL database.
    3. cloudwatch - stores logs in AWS CloudWatch.

    If the cloudwatch repository is used, the extension will automatically create a log group in CloudWatch. Also, check the CloudWatch repository documentation for additional configuration options.

    "},{"location":"configure/async/","title":"Asynchronous processing","text":"

    To avoid blocking the main thread, the extension uses a separate thread to write the audit logs. A separate thread will be started automatically along with the CKAN application.

    The thread is responsible for storing the logs in the configured repository.

    By default, we're using the threaded mode. However, if you want to disable the threaded mode, you can do this by setting the following configuration option in the CKAN configuration file:

    ckanext.event_audit.threaded_mode = false\n

    Disabling the threaded mode will cause the extension to write the logs in the main thread. This can be useful for debugging purposes.

    Note, that pairing it with the Cloudwatch repository is not recommended, as it can block the main thread for a long time. Network operations can be slow and can cause the application to hang for a while.

    If your custom repository involves a network operations, it's recommended to keep the threaded mode enabled.

    "},{"location":"configure/async/#batch-size","title":"Batch size","text":"

    The extension writes the logs in batches. The batch size can be adjusted by setting the following configuration option in the CKAN configuration file:

    ckanext.event_audit.batch.size = 50\n

    By default, we're accumulating 50 events before writing them to the repository.

    "},{"location":"configure/async/#batch-timeout","title":"Batch timeout","text":"

    Force push the events to the repository after this time in seconds since the last push:

    ckanext.event_audit.batch.timeout = 3600\n

    The default value is 3600 seconds (1 hour). This options is required to ensure that the logs are written to the repository in case of low activity.

    "},{"location":"configure/cloudwatch/","title":"Cloudwatch","text":"

    Using Cloudwatch repository requires you to configure the following options in the CKAN configuration file:

    ckanext.event_audit.cloudwatch.access_key = YOUR_ACCESS_KEY\nckanext.event_audit.cloudwatch.secret_key = YOUR_SECRET_KEY\nckanext.event_audit.cloudwatch.region = YOUR_REGION\n

    See the AWS documentation for more information on how to obtain these values and configure the AWS Cloudwatch service.

    "},{"location":"configure/ignore/","title":"Ignore events","text":"

    The extension provides a various set of configuration options to adjust the behavior of the audit logs.

    Warning

    These config options are applicable only for built-in tracking methods (API, Database) and not related to client's usage of the extension.

    "},{"location":"configure/ignore/#ignoring-categories","title":"Ignoring categories","text":"

    The extension allows to ignore specific categories of events. To do this, we have to set the following configuration option in the CKAN configuration file:

    ckanext.event_audit.ignore.categories = test\n

    By default, we're not ignoring any categories. The categories option is a comma-separated list of categories that should be ignored.

    Categories are arbitrary strings that can be used to group events.

    "},{"location":"configure/ignore/#ignoring-actions","title":"Ignoring actions","text":"

    The extension allows to ignore specific actions. To do this, we have to set the following configuration option in the CKAN configuration file:

    ckanext.event_audit.ignore.actions = test\n

    Some actions might be called more frequently than others, and we might not be interested in storing them. The actions option is a comma-separated list of actions that should be ignored.

    By default, we're excluding next actions from being stored:

    • editable_config_list
    • editable_config_change
    • get_site_user
    • ckanext_pages_list
    • user_show
    "},{"location":"configure/ignore/#ignoring-models","title":"Ignoring models","text":"

    The extension allows to ignore specific models. To do this, we have to set the following configuration option in the CKAN configuration file:

    ckanext.event_audit.ignore.models = User Package Resource\n

    By default, we're excluding next models from being stored:

    • Option
    "},{"location":"configure/tracking/","title":"In-built tracking","text":"

    There are two built-in trackers in the extension that are enabled by default and work out of the box - API and Database trackers.

    "},{"location":"configure/tracking/#api-tracker","title":"API tracker","text":"

    Captures all events that are triggered by the CKAN API. Everything that is called via tk.get_action will be tracked by this tracker, unless it's explicitly ignored by the configuration. See the ignore section for more details.

    To disable the API tracker, specify this in the configuration file:

    ckanext.event_audit.track.api = false\n

    We can ignore specific actions from being tracked by setting the ckanext.event_audit.ignore.actions configuration option. See the ignore section for more details.

    "},{"location":"configure/tracking/#database-tracker","title":"Database tracker","text":"

    We're utilising the SQLAlchemy\u2019s event system for tracking database interactions. The audit event creation will be triggered when the model is created, updated, or deleted.

    To disable the Database tracker, specify this in the configuration file:

    ckanext.event_audit.track.model = false\n

    We can ignore specific models from being tracked by setting the ckanext.event_audit.ignore.models configuration option. See the ignore section for more details.

    "},{"location":"configure/tracking/#custom-trackers","title":"Custom trackers","text":"

    You can create and write an event anywhere in your codebase.

    TODO: add link to usage docs

    "},{"location":"exporters/basic/","title":"Basic","text":"

    The exporters allow you to export the event audit logs to a different file format.

    The following exporters are available:

    1. CSV Exporter: Exports the event audit logs to a CSV file.
    2. JSON Exporter: Exports the event audit logs to a JSON file.
    3. TSV Exporter: Exports the event audit logs to a TSV file.
    4. XLSX Exporter: Exports the event audit logs to an XLSX file.

    Each exporter has its own configuration options. The configuration options are described in the respective exporter's documentation section.

    "},{"location":"exporters/basic/#base-exporter-class","title":"Base exporter class","text":"

    Base class for all exporters.

    Exporters are used to export a lsit of events to a specific file format.

    "},{"location":"exporters/basic/#event_audit.exporters.base.AbstractExporter.export","title":"export(events) abstractmethod","text":"

    Export events to a specific format.

    We are not providing a specific return type, because it will depend on the specific exporter implementation.

    PARAMETER DESCRIPTION events

    events to export

    TYPE: Iterable[Event]

    RETURNS DESCRIPTION Any

    exported data.

    TYPE: Any

    "},{"location":"exporters/basic/#event_audit.exporters.base.AbstractExporter.from_filters","title":"from_filters(filters, repo_name=None)","text":"

    Export events from a repo using the given filters.

    If repo_name is not provided, the active repo is used.

    PARAMETER DESCRIPTION filters

    search filters.

    TYPE: Filters

    repo_name

    name of the repo to use. Defaults to None.

    TYPE: str | None DEFAULT: None

    RETURNS DESCRIPTION Any

    exported data.

    TYPE: Any

    "},{"location":"exporters/csv/","title":"CSV exporter","text":""},{"location":"exporters/csv/#event_audit.exporters.csv.CSVExporter.__init__","title":"__init__(delimiter=',', quotechar='\"', quoting=QUOTE_ALL, ignore_fields=None)","text":"

    CSV exporter.

    PARAMETER DESCRIPTION delimiter

    delimiter. Defaults to \",\".

    TYPE: str DEFAULT: ','

    quotechar

    quote character. Defaults to '\"'.

    TYPE: str DEFAULT: '\"'

    quoting

    quoting. Defaults to QUOTE_ALL.

    TYPE: int DEFAULT: QUOTE_ALL

    ignore_fields

    fields to ignore. By default we ignore the \"result\" and \"payload\" fields.

    TYPE: list[str] | None DEFAULT: None

    "},{"location":"exporters/csv/#event_audit.exporters.csv.CSVExporter.export","title":"export(events)","text":"

    Export events to CSV format.

    PARAMETER DESCRIPTION events

    events to export.

    TYPE: Iterable[Event]

    RETURNS DESCRIPTION str | None

    str | None: CSV data.

    "},{"location":"exporters/json/","title":"JSON exporter","text":"

    Bases: AbstractExporter

    "},{"location":"exporters/json/#event_audit.exporters.json.JSONExporter.__init__","title":"__init__(stringify=True)","text":"

    JSON exporter.

    PARAMETER DESCRIPTION stringify

    whether to return a string or a dict. By default we return a string.

    TYPE: bool DEFAULT: True

    "},{"location":"exporters/json/#event_audit.exporters.json.JSONExporter.export","title":"export(events)","text":"

    Export events to JSON format.

    PARAMETER DESCRIPTION events

    events to export.

    TYPE: Iterable[Event]

    RETURNS DESCRIPTION list[dict[str, Any]] | str | None

    str | None: JSON data.

    "},{"location":"exporters/tsv/","title":"TSV exporter","text":""},{"location":"exporters/tsv/#event_audit.exporters.tsv.TSVExporter.__init__","title":"__init__(ignore_fields=None)","text":"

    TSV exporter.

    PARAMETER DESCRIPTION ignore_fields

    fields to ignore. By default we ignore the \"result\" and \"payload\" fields.

    TYPE: list[str] | None DEFAULT: None

    "},{"location":"exporters/xlsx/","title":"XLSX exporter","text":""},{"location":"exporters/xlsx/#event_audit.exporters.xlsx.XLSXExporter.__init__","title":"__init__(file_path, ignore_fields=None)","text":"

    XLSX exporter.

    PARAMETER DESCRIPTION file_path

    path to the file or BytesIO object to write the XLSX data.

    TYPE: str | BytesIO

    ignore_fields

    fields to ignore. By default we ignore the \"result\" and \"payload\" fields.

    TYPE: list[str] | None DEFAULT: None

    "},{"location":"exporters/xlsx/#event_audit.exporters.xlsx.XLSXExporter.export","title":"export(events)","text":"

    Export events to a XLSX file.

    PARAMETER DESCRIPTION events

    events to export.

    TYPE: Iterable[Event]

    RETURNS DESCRIPTION str | BytesIO | None

    str | BytesIO | None: path to the file or BytesIO object if the

    str | BytesIO | None

    export was successful, None otherwise.

    "},{"location":"repositories/abstract/","title":"Abstract","text":""},{"location":"repositories/abstract/#event_audit.repositories.base.AbstractRepository.__new__","title":"__new__(*args, **kwargs)","text":"

    Singleton pattern implementation.

    "},{"location":"repositories/abstract/#event_audit.repositories.base.AbstractRepository.build_event","title":"build_event(event_data)","text":"

    Build an event object from the provided data.

    PARAMETER DESCRIPTION event_data

    event data.

    TYPE: EventData

    RETURNS DESCRIPTION Event

    types.Event: event object.

    "},{"location":"repositories/abstract/#event_audit.repositories.base.AbstractRepository.enqueue_event","title":"enqueue_event(event)","text":"

    Enqueue an event to be written to the repository.

    PARAMETER DESCRIPTION event

    event to write.

    TYPE: Event

    RETURNS DESCRIPTION Result

    types.Result: result of the operation.

    "},{"location":"repositories/abstract/#event_audit.repositories.base.AbstractRepository.filter_events","title":"filter_events(filters) abstractmethod","text":"

    Filters events based on provided filter criteria.

    PARAMETER DESCRIPTION filters

    filters to apply.

    TYPE: Filters

    "},{"location":"repositories/abstract/#event_audit.repositories.base.AbstractRepository.get_event","title":"get_event(event_id) abstractmethod","text":"

    Retrieves a single event from the repository.

    PARAMETER DESCRIPTION event_id

    event ID.

    TYPE: str

    RETURNS DESCRIPTION Event | None

    types.Event | None: event object or None if not found.

    "},{"location":"repositories/abstract/#event_audit.repositories.base.AbstractRepository.get_name","title":"get_name() abstractmethod classmethod","text":"

    Return the name of the repository.

    RETURNS DESCRIPTION str

    name of the repository.

    TYPE: str

    "},{"location":"repositories/abstract/#event_audit.repositories.base.AbstractRepository.remove_all_events","title":"remove_all_events()","text":"

    Removes all events from the repository.

    RETURNS DESCRIPTION Result

    types.Result: result of the operation.

    "},{"location":"repositories/abstract/#event_audit.repositories.base.AbstractRepository.remove_event","title":"remove_event(event_id)","text":"

    Removes a single event from the repository.

    PARAMETER DESCRIPTION event_id

    event ID.

    TYPE: Any

    RETURNS DESCRIPTION Result

    types.Result: result of the operation.

    "},{"location":"repositories/abstract/#event_audit.repositories.base.AbstractRepository.test_connection","title":"test_connection() abstractmethod","text":"

    Test the connection to the repository.

    RETURNS DESCRIPTION bool

    whether the connection was successful.

    TYPE: bool

    "},{"location":"repositories/abstract/#event_audit.repositories.base.AbstractRepository.write_event","title":"write_event(event) abstractmethod","text":"

    Writes a single event to the repository.

    PARAMETER DESCRIPTION event

    event to write.

    TYPE: Event

    RETURNS DESCRIPTION Result

    types.Result: result of the operation.

    "},{"location":"repositories/abstract/#event_audit.repositories.base.AbstractRepository.write_events","title":"write_events(events)","text":"

    Write multiple events to the repository.

    PARAMETER DESCRIPTION events

    events to write.

    TYPE: Iterable[Event]

    RETURNS DESCRIPTION Result

    types.Result: result of the operation.

    "},{"location":"repositories/basic/","title":"Basic","text":"

    Repositories are the storages where the event audit logs are stored. There are a few basic repositories, that you can use out of the box:

    1. redis - the default repository, stores logs in Redis.
    2. postgres - stores logs in a PostgreSQL database.
    3. cloudwatch - stores logs in AWS CloudWatch.

    You can also implement your own repository. To do this, you need to create a new class that inherits from the AbstractRepository class and implement all the required methods.

    See the abstract repository documentation and custom repository documentation for more information.

    "},{"location":"repositories/cloudwatch/","title":"Cloudwatch repository","text":""},{"location":"repositories/cloudwatch/#event_audit.repositories.cloudwatch.CloudWatchRepository.__init__","title":"__init__(credentials=None, log_group='/ckan/event-audit', log_stream='event-audit-stream')","text":"

    CloudWatch repository.

    PARAMETER DESCRIPTION credentials

    AWS credentials. If not provided, the extension configuration will be used.

    TYPE: AWSCredentials | None DEFAULT: None

    log_group

    CloudWatch log group name.

    TYPE: str DEFAULT: '/ckan/event-audit'

    log_stream

    CloudWatch log stream name.

    TYPE: str DEFAULT: 'event-audit-stream'

    "},{"location":"repositories/cloudwatch/#event_audit.repositories.cloudwatch.CloudWatchRepository.filter_events","title":"filter_events(filters)","text":"

    Filters events based on provided filter criteria.

    PARAMETER DESCRIPTION filters

    filters to apply.

    TYPE: Filters

    "},{"location":"repositories/cloudwatch/#event_audit.repositories.cloudwatch.CloudWatchRepository.get_event","title":"get_event(event_id)","text":"

    Retrieves a single event from the repository.

    PARAMETER DESCRIPTION event_id

    event ID.

    TYPE: str

    RETURNS DESCRIPTION Optional[Event]

    types.Event | None: event object or None if not found.

    "},{"location":"repositories/cloudwatch/#event_audit.repositories.cloudwatch.CloudWatchRepository.remove_all_events","title":"remove_all_events()","text":"

    Removes all events from the repository.

    RETURNS DESCRIPTION Result

    types.Result: result of the operation.

    "},{"location":"repositories/cloudwatch/#event_audit.repositories.cloudwatch.CloudWatchRepository.remove_event","title":"remove_event(event_id)","text":"

    Remove operation is not supported for CloudWatch logs.

    As of today, you cannot delete a single log event from CloudWatch log stream, the alternative will be using Lambda functions: set a Lambda function trigger, filter all logs, then write the remaining logs to a new log group/stream, then delete the original log stream.

    It's potentially too expensive to do this operation, so it's not implemented.

    Note

    The remove single event operation is not supported

    "},{"location":"repositories/cloudwatch/#event_audit.repositories.cloudwatch.CloudWatchRepository.test_connection","title":"test_connection()","text":"

    Tests the connection to the repository.

    RETURNS DESCRIPTION bool

    whether the connection was successful.

    TYPE: bool

    "},{"location":"repositories/cloudwatch/#event_audit.repositories.cloudwatch.CloudWatchRepository.write_event","title":"write_event(event)","text":"

    Writes a single event to the repository.

    PARAMETER DESCRIPTION event

    event to write.

    TYPE: Event

    RETURNS DESCRIPTION Result

    types.Result: result of the operation.

    "},{"location":"repositories/custom/","title":"Custom","text":"

    Here you can see a naive example of how to implement a custom repository, that stores logs in a json file.

    from ckanext.event_audit.repositories import AbstractRepository\n\nclass FileRepository(AbstractRepository):\n    def __init__(self, file_path: str | None = None):\n        self.file_path = file_path or '/tmp/event_audit.json'\n\n    def log(self) -> str:\n        return \"file\"\n\n    def write_event(self, event: types.Event) -> types.Result:\n        with open(self.file_path, 'a') as f:\n            data = json.load(f)\n            data[event.id] = event.model_dump()\n\n            f.write(json.dumps(data))\n\n        return types.Result(success=True)\n\n    def get_event(self, event_id: Any) -> types.Event | None:\n        with open(self.file_path, 'r') as f:\n            data = json.load(f)\n\n            if event_id in data:\n                return types.Event.model_validate(data[event_id])\n\n        return None\n\n    def filter_events(self, filters: types.Filters) -> list[types.Event]:\n        with open(self.file_path, 'r') as f:\n            data = json.load(f)\n\n            result = []\n\n            for event in data.values():\n                if _match_filters(event, filters):\n                    result.append(types.Event.model_validate(event))\n\n            return result\n\n    def _match_filters(self, event: types.EventData, filters: types.Filters) -> bool:\n        ...\n\n    def test_connection(self) -> types.Result:\n        return types.Result(success=True)\n

    In this version, it doesn't implement the remove_event and remove_events methods, but you can implement them in the same way as the other methods. If the repository able to remove one or multiple events, it must inherits from the respective class - RemoveSingle or RemoveAll. For example:

    import os\n\nfrom ckanext.event_audit.repositories import AbstractRepository, RemoveSingle, RemoveAll\n\nclass FileRepository(AbstractRepository, RemoveSingle, RemoveAll):\n    ...\n\n    def remove_event(self, event_id: Any) -> types.Result:\n        with open(self.file_path, 'w') as f:\n            data = json.load(f)\n\n            if event_id in data:\n                del data[event_id]\n                f.write(json.dumps(data))\n\n                return types.Result(success=True)\n\n        return types.Result(success=False, message='Event not found')\n\n    def remove_events(self, filters: types.Filters) -> types.Result:\n        \"\"\"Removes the file if exists.\"\"\"\n\n        if os.path.exists(self.file_path):\n            os.remove(self.file_path)\n\n        return types.Result(success=True)\n
    "},{"location":"repositories/postgres/","title":"Postgres repository","text":""},{"location":"repositories/postgres/#event_audit.repositories.postgres.PostgresRepository.filter_events","title":"filter_events(filters)","text":"

    Filters events based on provided filter criteria.

    PARAMETER DESCRIPTION filters

    filters to apply.

    TYPE: Filters

    "},{"location":"repositories/postgres/#event_audit.repositories.postgres.PostgresRepository.get_event","title":"get_event(event_id)","text":"

    Retrieves a single event from the repository.

    PARAMETER DESCRIPTION event_id

    event ID.

    TYPE: str

    RETURNS DESCRIPTION Event | None

    types.Event | None: event object or None if not found.

    "},{"location":"repositories/postgres/#event_audit.repositories.postgres.PostgresRepository.remove_all_events","title":"remove_all_events()","text":"

    Removes all events from the repository.

    RETURNS DESCRIPTION Result

    types.Result: result of the operation.

    "},{"location":"repositories/postgres/#event_audit.repositories.postgres.PostgresRepository.remove_event","title":"remove_event(event_id, session=None, defer_commit=False)","text":"

    Removes a single event from the repository.

    PARAMETER DESCRIPTION event_id

    event ID.

    TYPE: str

    session

    session to use.

    TYPE: Session | None DEFAULT: None

    defer_commit

    whether to defer the commit.

    TYPE: bool DEFAULT: False

    RETURNS DESCRIPTION Result

    types.Result: result of the operation.

    "},{"location":"repositories/postgres/#event_audit.repositories.postgres.PostgresRepository.test_connection","title":"test_connection()","text":"

    Tests the connection to the repository.

    RETURNS DESCRIPTION bool

    whether the connection was successful.

    TYPE: bool

    "},{"location":"repositories/postgres/#event_audit.repositories.postgres.PostgresRepository.write_event","title":"write_event(event, session=None, defer_commit=False)","text":"

    Writes a single event to the repository.

    PARAMETER DESCRIPTION event

    event to write.

    TYPE: Event

    session

    session to use.

    TYPE: Session | None DEFAULT: None

    defer_commit

    whether to defer the commit.

    TYPE: bool DEFAULT: False

    RETURNS DESCRIPTION Result

    types.Result: result of the operation.

    "},{"location":"repositories/postgres/#event_audit.repositories.postgres.PostgresRepository.write_events","title":"write_events(events)","text":"

    Write multiple events to the repository.

    PARAMETER DESCRIPTION events

    events to write.

    TYPE: Iterable[Event]

    RETURNS DESCRIPTION Result

    types.Result: result of the operation.

    "},{"location":"repositories/redis/","title":"Redis repository","text":""},{"location":"repositories/redis/#event_audit.repositories.redis.RedisRepository.filter_events","title":"filter_events(filters)","text":"

    Filters events based on patterns generated from the provided filters.

    PARAMETER DESCRIPTION filters

    filters to apply.

    TYPE: Filters

    "},{"location":"repositories/redis/#event_audit.repositories.redis.RedisRepository.get_event","title":"get_event(event_id)","text":"

    Get an event by its ID.

    PARAMETER DESCRIPTION event_id

    event ID.

    TYPE: float

    "},{"location":"repositories/redis/#event_audit.repositories.redis.RedisRepository.remove_all_events","title":"remove_all_events()","text":"

    Removes all events from the repository.

    RETURNS DESCRIPTION Result

    types.Result: result of the operation.

    "},{"location":"repositories/redis/#event_audit.repositories.redis.RedisRepository.remove_event","title":"remove_event(event_id)","text":"

    Removes an event by its ID.

    PARAMETER DESCRIPTION event_id

    event ID.

    TYPE: float

    RETURNS DESCRIPTION Result

    types.Result: result of the operation.

    "},{"location":"repositories/redis/#event_audit.repositories.redis.RedisRepository.test_connection","title":"test_connection()","text":"

    Tests the connection to the repository.

    RETURNS DESCRIPTION bool

    whether the connection was successful.

    TYPE: bool

    "},{"location":"repositories/redis/#event_audit.repositories.redis.RedisRepository.write_event","title":"write_event(event)","text":"

    Writes an event to Redis.

    PARAMETER DESCRIPTION event

    event to write.

    TYPE: Event

    RETURNS DESCRIPTION Result

    types.Result: result of the operation.

    "},{"location":"repositories/test/","title":"Test","text":""},{"location":"repositories/test/#removesingle-class","title":"RemoveSingle class","text":"

    If repository supports removing single log entries, it should inherit the RemoveSingle class.

    Mark the repository as supporting remove single event.

    If the repository supports remove single event, it should inherit from this class.

    Mark the repository as supporting remove all events.

    If the repository supports remove all events, it should inherit from this class.

    "}]} \ No newline at end of file +{"config":{"lang":["en"],"separator":"[\\s\\-\\.\\_]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Home","text":""},{"location":"#ckanext-event-audit","title":"ckanext-event-audit","text":"

    This extension will capture and retain a comprehensive record of all changes within a CKAN app.

    "},{"location":"#developer-installation","title":"Developer installation","text":"

    To install ckanext-event-audit for development, activate your CKAN virtualenv and do:

    git clone https://github.com/DataShades/ckanext-event-audit.git\ncd ckanext-event-audit\npip install -e .\npip install -r dev-requirements.txt\n
    "},{"location":"#tests","title":"Tests","text":"

    To run the tests, do:

    pytest --ckan-ini=test.ini\n
    "},{"location":"#license","title":"License","text":"

    AGPL

    "},{"location":"cli/","title":"CLI","text":""},{"location":"cli/#event_audit.cli.export_data","title":"export_data(exporter_name, start, end, config)","text":"

    Export data using the specified exporter.

    PARAMETER DESCRIPTION exporter_name

    The name of the exporter.

    TYPE: str

    start

    The start date string in %Y-%m-%d format.

    TYPE: str

    end

    The end date string in %Y-%m-%d format.

    TYPE: str | None

    config

    The exporter config in JSON format. See the exporter's documentation for args details.

    TYPE: str | None

    RETURNS DESCRIPTION str

    The exported data

    Example

    $ ckan event-audit export-data csv --start=2024-11-11 > report.csv

    $ ckan event-audit export-data json --start=2024-11-11 | jq '[.[] | {id, category, action}]'

    $ ckan event-audit export-data xlsx --start=2024-11-11 --config='{\"file_path\": \"/tmp/test.xlsx\"}'

    Source code in ckanext/event_audit/cli.py
    @event_audit.command()\n@click.argument(\"exporter_name\", type=str)\n@click.option(\n    \"--start\",\n    required=True,\n    type=click.DateTime(formats=[\"%Y-%m-%d\"]),\n    help=\"ISO format start date\",\n)\n@click.option(\n    \"--end\",\n    required=False,\n    type=click.DateTime(formats=[\"%Y-%m-%d\"]),\n    help=\"ISO format end date\",\n)\n@click.option(\"--config\", required=False, type=str, help=\"Custom config in JSON format\")\ndef export_data(exporter_name: str, start: dt, end: dt | None, config: str | None):\n    \"\"\"Export data using the specified exporter.\n\n    Args:\n        exporter_name (str): The name of the exporter.\n        start (str): The start date string in %Y-%m-%d format.\n        end (str | None): The end date string in %Y-%m-%d format.\n        config (str | None): The exporter config in JSON format. See the exporter's\n            documentation for args details.\n\n    Returns:\n        str : The exported data\n\n    Example:\n        $ ckan event-audit export-data csv --start=2024-11-11 > report.csv\n\n        $ ckan event-audit export-data json --start=2024-11-11 | jq '[.[] |\n            {id, category, action}]'\n\n        $ ckan event-audit export-data xlsx --start=2024-11-11\n            --config='{\"file_path\": \"/tmp/test.xlsx\"}'\n    \"\"\"\n    start = UTC.localize(start) if start else None\n    end = UTC.localize(end) if end else None\n\n    try:\n        config_dict = json.loads(config or \"{}\")\n    except json.JSONDecodeError:\n        return click.secho(\"Invalid JSON format for config.\")\n\n    try:\n        exporter = utils.get_exporter(exporter_name)(**config_dict)\n    except TypeError as e:\n        return click.secho(f\"Invalid exporter config: {config}. Error: {e}\", fg=\"red\")\n    except ValueError as e:\n        return click.secho(e, fg=\"red\")\n\n    if start and end and start > end:\n        return click.secho(\"Start date must be before the end date.\", fg=\"red\")\n\n    click.echo(exporter.from_filters(types.Filters(time_from=start, time_to=end)))\n
    "},{"location":"cli/#event_audit.cli.remove_events","title":"remove_events(repository, start, end)","text":"

    Remove events from the repository by time range.

    PARAMETER DESCRIPTION repository

    The repository name. If not provided, the active repository will be used.

    TYPE: str | None

    start

    The start date string in %Y-%m-%d format.

    TYPE: str

    end

    The end date string in %Y-%m-%d format.

    TYPE: str | None

    Example

    $ ckan event-audit remove-events --start=2024-11-11 --end=2024-11-12

    Source code in ckanext/event_audit/cli.py
    @event_audit.command()\n@click.option(\"--repository\", required=False, help=\"The repository name\")\n@click.option(\n    \"--start\",\n    required=False,\n    type=click.DateTime(formats=[\"%Y-%m-%d\"]),\n    help=\"ISO format start date\",\n)\n@click.option(\n    \"--end\",\n    required=False,\n    type=click.DateTime(formats=[\"%Y-%m-%d\"]),\n    help=\"ISO format end date\",\n)\ndef remove_events(repository: str | None, start: dt | None, end: dt | None):\n    \"\"\"Remove events from the repository by time range.\n\n    Args:\n        repository (str | None): The repository name. If not provided, the\n            active repository will be used.\n        start (str): The start date string in %Y-%m-%d format.\n        end (str | None): The end date string in %Y-%m-%d format.\n\n    Example:\n        $ ckan event-audit remove-events --start=2024-11-11 --end=2024-11-12\n    \"\"\"\n    start = UTC.localize(start) if start else None\n    end = UTC.localize(end) if end else None\n\n    if start and end and start > end:\n        return click.secho(\"Start date must be before the end date.\", fg=\"red\")\n\n    try:\n        repo = utils.get_repo(repository) if repository else utils.get_active_repo()\n    except ValueError:\n        return click.secho(f\"Unknown repository: {repository}\", fg=\"red\")\n\n    if not (start or end) and not isinstance(repo, repositories.RemoveAll):\n        return click.secho(\n            f\"Repository {repository} does not support removing events.\", fg=\"red\"\n        )\n\n    if not isinstance(repo, repositories.RemoveFiltered):\n        if start or end:\n            return click.secho(\n                (\n                    f\"Repository {repository} does not support removing events \"\n                    \"by time range. \"\n                    \"Please remove the --start and --end flags to delete all events.\"\n                ),\n                fg=\"red\",\n            )\n        return repo.remove_all_events()\n\n    return repo.remove_events(types.Filters(time_from=start, time_to=end))\n
    "},{"location":"install/","title":"Installation","text":""},{"location":"install/#requirements","title":"Requirements","text":"

    Compatibility with core CKAN versions:

    CKAN version Compatible? 2.9 no 2.10 yes 2.11 yes master yes"},{"location":"install/#installation_1","title":"Installation","text":"
    1. Install the extension from PyPI:

      pip install ckanext-event-audit\n

    2. Enable the plugin in your CKAN configuration file (e.g. ckan.ini or production.ini):

      ckan.plugins = ... event_audit ...\n

    3. Run DB migrations:

      ckan db upgrade -p event_audit\n

    4. Configure the extension up to your needs and you're ready to go. See the documentation for more details about the configuration options.

    "},{"location":"interfaces/","title":"Interfaces","text":""},{"location":"interfaces/#ieventaudit","title":"IEventAudit","text":"

    Extend functionality of ckanext-event-audit.

    Example:

    import ckan.plugins as p\n\nfrom ckanext.event_audit.interfaces import IEventAudit\nfrom ckanext.event_audit.repositories import AbstractRepository\nfrom ckanext.event_audit.exporters import AbstractExporter\n\nclass MyPlugin(p.SingletonPlugin):\n    p.implements(IEventAudit, inherit=True)\n\n    def register_repository(self) -> dict[str, type[AbstractRepository]]:\n        return {\n            \"my_repo\": MyRepository,\n        }\n\n    def register_exporter(self) -> dict[str, type[AbstractExporter]]:\n        return {\n            \"my_exporter\": MyExporter,\n        }\n\n    def skip_event(self, event: types.Event) -> bool:\n        if event.category == \"api\" and event.action == \"status_show\":\n            return True\n\n        if event.category == \"model\" and event.action_object == \"Dashboard\":\n            return True\n\n        return False\n

    "},{"location":"interfaces/#event_audit.interfaces.IEventAudit.register_exporter","title":"register_exporter()","text":"

    Return the exporters provided by this plugin.

    Example
    def register_exporter(self):\n    return {\n        \"csv\": CSVExporter,\n    }\n
    RETURNS DESCRIPTION dict[str, type[AbstractExporter]]

    mapping of exporter names to exporter classes

    "},{"location":"interfaces/#event_audit.interfaces.IEventAudit.register_repository","title":"register_repository()","text":"

    Return the repositories provided by this plugin.

    Example
    def register_repository(self):\n    return {\n        \"my_repo\": MyRepository,\n    }\n
    RETURNS DESCRIPTION dict[str, type[AbstractRepository]]

    mapping of repository names to repository classes

    "},{"location":"interfaces/#event_audit.interfaces.IEventAudit.skip_event","title":"skip_event(event)","text":"

    Skip an event.

    This method is called before writing the event to the repository.

    Example
    def skip_event(self, event: types.Event) -> bool:\n    if event.category == \"api\" and event.action == \"status_show\":\n        return True\n\n    if  event.category == \"model\"  and event.action_object == \"Dashboard\":\n        return True\n\n    return False\n
    RETURNS DESCRIPTION bool

    True if the event should be skipped, False otherwise

    "},{"location":"usage/","title":"Usage","text":"

    To use an event audit in your extension, you should get an instance of the repository class. There are two ways to do this:

    1. Using the get_repo function:

      import ckanext.event_audit.utils as utils\n\nrepo = utils.get_active_repo()\n\nevent = repo.build_event({\"category\": \"xxx\", \"action\": \"xxx\"})\n\nrepo.write_event(event)\n

      The get_active_repo function will return an instance of the active repository class that is configured in the CKAN configuration file.

    2. Using the get_repo function with a specific repository:

      import ckanext.event_audit.utils as utils\n\nrepo = utils.get_repo(\"file\")\n\nevent = repo.build_event({\"category\": \"xxx\", \"action\": \"xxx\"})\n\nrepo.write_event(event)\n

      The get_repo function will return an instance of the repository class that is specified in the argument. You can use this method to get a specific repository instance.

    "},{"location":"utils/","title":"Utility Functions","text":""},{"location":"utils/#event_audit.utils.get_active_repo","title":"get_active_repo()","text":"

    Get the active repository.

    The active repository is the one that is currently configured in the extension configuration.

    RETURNS DESCRIPTION AbstractRepository

    The active repository.

    "},{"location":"utils/#event_audit.utils.get_available_exporters","title":"get_available_exporters()","text":"

    Retrieve a dictionary of available exporters.

    This function collects and returns a dictionary where the keys are exporter names (as strings) and the values are the corresponding exporter classes.

    RETURNS DESCRIPTION dict[str, type[AbstractExporter]]

    A dictionary mapping exporter names to their respective exporter classes.

    "},{"location":"utils/#event_audit.utils.get_available_repos","title":"get_available_repos()","text":"

    Retrieve a dictionary of available repositories.

    This function collects and returns a dictionary where the keys are repository names (as strings) and the values are the corresponding repository classes.

    RETURNS DESCRIPTION dict[str, type[AbstractRepository]]

    A dictionary mapping repository names to their respective repository classes.

    "},{"location":"utils/#event_audit.utils.get_exporter","title":"get_exporter(exporter_name)","text":"

    Retrieve an exporter class by name.

    This function retrieves an exporter class by name. If the exporter is not found, a ValueError is raised.

    PARAMETER DESCRIPTION exporter_name

    The name of the exporter to retrieve.

    TYPE: str

    RETURNS DESCRIPTION type[AbstractExporter]

    The exporter class.

    "},{"location":"utils/#event_audit.utils.get_repo","title":"get_repo(repo_name)","text":"

    Retrieve a repository class by name.

    This function retrieves a repository class by name. If the repository is not found, a ValueError is raised.

    PARAMETER DESCRIPTION repo_name

    The name of the repository to retrieve.

    TYPE: str

    RETURNS DESCRIPTION AbstractRepository

    The repository class.

    "},{"location":"utils/#event_audit.utils.test_active_connection","title":"test_active_connection()","text":"

    Test the connection to the active repository.

    When we test the connection, we store the result in the repository object, so we can reuse it later.

    RETURNS DESCRIPTION bool

    whether the connection is active

    "},{"location":"validators/","title":"Validators","text":""},{"location":"validators/#event_audit.logic.validators.audit_repo_exists","title":"audit_repo_exists(value, context)","text":"

    Check if the repository with the given name is registered.

    PARAMETER DESCRIPTION value

    The repository name.

    TYPE: Any

    context

    The CKAN context.

    TYPE: Context

    RETURNS DESCRIPTION Any

    The repository name if it exists.

    TYPE: Any

    RAISES DESCRIPTION Invalid

    If the repository does not exist.

    Source code in ckanext/event_audit/logic/validators.py
    def audit_repo_exists(value: Any, context: Context) -> Any:\n    \"\"\"Check if the repository with the given name is registered.\n\n    Args:\n        value (Any): The repository name.\n        context (Context): The CKAN context.\n\n    Returns:\n        Any: The repository name if it exists.\n\n    Raises:\n        tk.Invalid: If the repository does not exist.\n    \"\"\"\n    if value not in utils.get_available_repos():\n        raise tk.Invalid(f\"Repository `{value}` is not registered\")\n\n    return value\n
    "},{"location":"configure/active_repo/","title":"Active repository","text":"

    The event audit logs are stored in a configurable storages, we call them repositories.

    The default repository is redis, but it can be changed to a different one. To do this, we have to set the following configuration options in the CKAN configuration file:

    ckanext.event_audit.active_repo = postgres\n

    The following repositories are available:

    1. redis - the default repository, stores logs in Redis.
    2. postgres - stores logs in a PostgreSQL database.
    3. cloudwatch - stores logs in AWS CloudWatch.

    If the cloudwatch repository is used, the extension will automatically create a log group in CloudWatch. Also, check the CloudWatch repository documentation for additional configuration options.

    "},{"location":"configure/async/","title":"Asynchronous processing","text":"

    To avoid blocking the main thread, the extension uses a separate thread to write the audit logs. A separate thread will be started automatically along with the CKAN application.

    The thread is responsible for storing the logs in the configured repository.

    By default, we're using the threaded mode. However, if you want to disable the threaded mode, you can do this by setting the following configuration option in the CKAN configuration file:

    ckanext.event_audit.threaded_mode = false\n

    Disabling the threaded mode will cause the extension to write the logs in the main thread. This can be useful for debugging purposes.

    Note, that pairing it with the Cloudwatch repository is not recommended, as it can block the main thread for a long time. Network operations can be slow and can cause the application to hang for a while.

    If your custom repository involves a network operations, it's recommended to keep the threaded mode enabled.

    "},{"location":"configure/async/#batch-size","title":"Batch size","text":"

    The extension writes the logs in batches. The batch size can be adjusted by setting the following configuration option in the CKAN configuration file:

    ckanext.event_audit.batch.size = 50\n

    By default, we're accumulating 50 events before writing them to the repository.

    "},{"location":"configure/async/#batch-timeout","title":"Batch timeout","text":"

    Force push the events to the repository after this time in seconds since the last push:

    ckanext.event_audit.batch.timeout = 3600\n

    The default value is 3600 seconds (1 hour). This options is required to ensure that the logs are written to the repository in case of low activity.

    "},{"location":"configure/cloudwatch/","title":"Cloudwatch","text":"

    Using Cloudwatch repository requires you to configure the following options in the CKAN configuration file:

    ckanext.event_audit.cloudwatch.access_key = YOUR_ACCESS_KEY\nckanext.event_audit.cloudwatch.secret_key = YOUR_SECRET_KEY\nckanext.event_audit.cloudwatch.region = YOUR_REGION\n

    See the AWS documentation for more information on how to obtain these values and configure the AWS Cloudwatch service.

    "},{"location":"configure/ignore/","title":"Ignore events","text":"

    The extension provides a various set of configuration options to adjust the behavior of the audit logs.

    Warning

    These config options are applicable only for built-in tracking methods (API, Database) and not related to client's usage of the extension.

    "},{"location":"configure/ignore/#ignoring-categories","title":"Ignoring categories","text":"

    The extension allows to ignore specific categories of events. To do this, we have to set the following configuration option in the CKAN configuration file:

    ckanext.event_audit.ignore.categories = test\n

    By default, we're not ignoring any categories. The categories option is a comma-separated list of categories that should be ignored.

    Categories are arbitrary strings that can be used to group events.

    "},{"location":"configure/ignore/#ignoring-actions","title":"Ignoring actions","text":"

    The extension allows to ignore specific actions. To do this, we have to set the following configuration option in the CKAN configuration file:

    ckanext.event_audit.ignore.actions = test\n

    Some actions might be called more frequently than others, and we might not be interested in storing them. The actions option is a comma-separated list of actions that should be ignored.

    By default, we're excluding next actions from being stored:

    • editable_config_list
    • editable_config_change
    • get_site_user
    • ckanext_pages_list
    • user_show
    "},{"location":"configure/ignore/#ignoring-models","title":"Ignoring models","text":"

    The extension allows to ignore specific models. To do this, we have to set the following configuration option in the CKAN configuration file:

    ckanext.event_audit.ignore.models = User Package Resource\n

    By default, we're excluding next models from being stored:

    • Option
    "},{"location":"configure/tracking/","title":"In-built tracking","text":"

    There are two built-in trackers in the extension that are enabled by default and work out of the box - API and Database trackers.

    "},{"location":"configure/tracking/#api-tracker","title":"API tracker","text":"

    Captures all events that are triggered by the CKAN API. Everything that is called via tk.get_action will be tracked by this tracker, unless it's explicitly ignored by the configuration. See the ignore section for more details.

    To disable the API tracker, specify this in the configuration file:

    ckanext.event_audit.track.api = false\n

    We can ignore specific actions from being tracked by setting the ckanext.event_audit.ignore.actions configuration option. See the ignore section for more details.

    "},{"location":"configure/tracking/#database-tracker","title":"Database tracker","text":"

    We're utilising the SQLAlchemy\u2019s event system for tracking database interactions. The audit event creation will be triggered when the model is created, updated, or deleted.

    To disable the Database tracker, specify this in the configuration file:

    ckanext.event_audit.track.model = false\n

    We can ignore specific models from being tracked by setting the ckanext.event_audit.ignore.models configuration option. See the ignore section for more details.

    "},{"location":"configure/tracking/#custom-trackers","title":"Custom trackers","text":"

    You can create and write an event anywhere in your codebase.

    TODO: add link to usage docs

    "},{"location":"exporters/basic/","title":"Basic","text":"

    The exporters allow you to export the event audit logs to a different file format.

    The following exporters are available:

    1. CSV Exporter: Exports the event audit logs to a CSV file.
    2. JSON Exporter: Exports the event audit logs to a JSON file.
    3. TSV Exporter: Exports the event audit logs to a TSV file.
    4. XLSX Exporter: Exports the event audit logs to an XLSX file.

    Each exporter has its own configuration options. The configuration options are described in the respective exporter's documentation section.

    "},{"location":"exporters/basic/#base-exporter-class","title":"Base exporter class","text":"

    Base class for all exporters.

    Exporters are used to export a lsit of events to a specific file format.

    "},{"location":"exporters/basic/#event_audit.exporters.base.AbstractExporter.export","title":"export(events) abstractmethod","text":"

    Export events to a specific format.

    We are not providing a specific return type, because it will depend on the specific exporter implementation.

    PARAMETER DESCRIPTION events

    events to export

    TYPE: Iterable[Event]

    RETURNS DESCRIPTION Any

    exported data.

    TYPE: Any

    "},{"location":"exporters/basic/#event_audit.exporters.base.AbstractExporter.from_filters","title":"from_filters(filters, repo_name=None)","text":"

    Export events from a repo using the given filters.

    If repo_name is not provided, the active repo is used.

    PARAMETER DESCRIPTION filters

    search filters.

    TYPE: Filters

    repo_name

    name of the repo to use. Defaults to None.

    TYPE: str | None DEFAULT: None

    RETURNS DESCRIPTION Any

    exported data.

    TYPE: Any

    "},{"location":"exporters/csv/","title":"CSV exporter","text":""},{"location":"exporters/csv/#event_audit.exporters.csv.CSVExporter.__init__","title":"__init__(delimiter=',', quotechar='\"', quoting=QUOTE_ALL, ignore_fields=None)","text":"

    CSV exporter.

    PARAMETER DESCRIPTION delimiter

    delimiter. Defaults to \",\".

    TYPE: str DEFAULT: ','

    quotechar

    quote character. Defaults to '\"'.

    TYPE: str DEFAULT: '\"'

    quoting

    quoting. Defaults to QUOTE_ALL.

    TYPE: int DEFAULT: QUOTE_ALL

    ignore_fields

    fields to ignore. By default we ignore the \"result\" and \"payload\" fields.

    TYPE: list[str] | None DEFAULT: None

    "},{"location":"exporters/csv/#event_audit.exporters.csv.CSVExporter.export","title":"export(events)","text":"

    Export events to CSV format.

    PARAMETER DESCRIPTION events

    events to export.

    TYPE: Iterable[Event]

    RETURNS DESCRIPTION str | None

    str | None: CSV data.

    "},{"location":"exporters/json/","title":"JSON exporter","text":"

    Bases: AbstractExporter

    "},{"location":"exporters/json/#event_audit.exporters.json.JSONExporter.__init__","title":"__init__(stringify=True)","text":"

    JSON exporter.

    PARAMETER DESCRIPTION stringify

    whether to return a string or a dict. By default we return a string.

    TYPE: bool DEFAULT: True

    "},{"location":"exporters/json/#event_audit.exporters.json.JSONExporter.export","title":"export(events)","text":"

    Export events to JSON format.

    PARAMETER DESCRIPTION events

    events to export.

    TYPE: Iterable[Event]

    RETURNS DESCRIPTION list[dict[str, Any]] | str | None

    str | None: JSON data.

    "},{"location":"exporters/tsv/","title":"TSV exporter","text":""},{"location":"exporters/tsv/#event_audit.exporters.tsv.TSVExporter.__init__","title":"__init__(ignore_fields=None)","text":"

    TSV exporter.

    PARAMETER DESCRIPTION ignore_fields

    fields to ignore. By default we ignore the \"result\" and \"payload\" fields.

    TYPE: list[str] | None DEFAULT: None

    "},{"location":"exporters/xlsx/","title":"XLSX exporter","text":""},{"location":"exporters/xlsx/#event_audit.exporters.xlsx.XLSXExporter.__init__","title":"__init__(file_path, ignore_fields=None)","text":"

    XLSX exporter.

    PARAMETER DESCRIPTION file_path

    path to the file or BytesIO object to write the XLSX data.

    TYPE: str | BytesIO

    ignore_fields

    fields to ignore. By default we ignore the \"result\" and \"payload\" fields.

    TYPE: list[str] | None DEFAULT: None

    "},{"location":"exporters/xlsx/#event_audit.exporters.xlsx.XLSXExporter.export","title":"export(events)","text":"

    Export events to a XLSX file.

    PARAMETER DESCRIPTION events

    events to export.

    TYPE: Iterable[Event]

    RETURNS DESCRIPTION str | BytesIO | None

    str | BytesIO | None: path to the file or BytesIO object if the

    str | BytesIO | None

    export was successful, None otherwise.

    "},{"location":"repositories/abstract/","title":"Abstract","text":""},{"location":"repositories/abstract/#event_audit.repositories.base.AbstractRepository.__new__","title":"__new__(*args, **kwargs)","text":"

    Singleton pattern implementation.

    "},{"location":"repositories/abstract/#event_audit.repositories.base.AbstractRepository.build_event","title":"build_event(event_data)","text":"

    Build an event object from the provided data.

    PARAMETER DESCRIPTION event_data

    event data.

    TYPE: EventData

    RETURNS DESCRIPTION Event

    types.Event: event object.

    "},{"location":"repositories/abstract/#event_audit.repositories.base.AbstractRepository.enqueue_event","title":"enqueue_event(event)","text":"

    Enqueue an event to be written to the repository.

    PARAMETER DESCRIPTION event

    event to write.

    TYPE: Event

    RETURNS DESCRIPTION Result

    types.Result: result of the operation.

    "},{"location":"repositories/abstract/#event_audit.repositories.base.AbstractRepository.filter_events","title":"filter_events(filters) abstractmethod","text":"

    Filters events based on provided filter criteria.

    PARAMETER DESCRIPTION filters

    filters to apply.

    TYPE: Filters

    "},{"location":"repositories/abstract/#event_audit.repositories.base.AbstractRepository.get_event","title":"get_event(event_id) abstractmethod","text":"

    Retrieves a single event from the repository.

    PARAMETER DESCRIPTION event_id

    event ID.

    TYPE: str

    RETURNS DESCRIPTION Event | None

    types.Event | None: event object or None if not found.

    "},{"location":"repositories/abstract/#event_audit.repositories.base.AbstractRepository.get_name","title":"get_name() abstractmethod classmethod","text":"

    Return the name of the repository.

    RETURNS DESCRIPTION str

    name of the repository.

    TYPE: str

    "},{"location":"repositories/abstract/#event_audit.repositories.base.AbstractRepository.remove_all_events","title":"remove_all_events()","text":"

    Removes all events from the repository.

    RETURNS DESCRIPTION Result

    types.Result: result of the operation.

    "},{"location":"repositories/abstract/#event_audit.repositories.base.AbstractRepository.remove_event","title":"remove_event(event_id)","text":"

    Removes a single event from the repository.

    PARAMETER DESCRIPTION event_id

    event ID.

    TYPE: Any

    RETURNS DESCRIPTION Result

    types.Result: result of the operation.

    "},{"location":"repositories/abstract/#event_audit.repositories.base.AbstractRepository.remove_events","title":"remove_events(filters)","text":"

    Removes a filtered set of events from the repository.

    PARAMETER DESCRIPTION filters

    filters to apply.

    TYPE: Filters

    RETURNS DESCRIPTION Result

    types.Result: result of the operation.

    "},{"location":"repositories/abstract/#event_audit.repositories.base.AbstractRepository.test_connection","title":"test_connection() abstractmethod","text":"

    Test the connection to the repository.

    RETURNS DESCRIPTION bool

    whether the connection was successful.

    TYPE: bool

    "},{"location":"repositories/abstract/#event_audit.repositories.base.AbstractRepository.write_event","title":"write_event(event) abstractmethod","text":"

    Writes a single event to the repository.

    PARAMETER DESCRIPTION event

    event to write.

    TYPE: Event

    RETURNS DESCRIPTION Result

    types.Result: result of the operation.

    "},{"location":"repositories/abstract/#event_audit.repositories.base.AbstractRepository.write_events","title":"write_events(events)","text":"

    Write multiple events to the repository.

    PARAMETER DESCRIPTION events

    events to write.

    TYPE: Iterable[Event]

    RETURNS DESCRIPTION Result

    types.Result: result of the operation.

    "},{"location":"repositories/basic/","title":"Basic","text":"

    Repositories are the storages where the event audit logs are stored. There are a few basic repositories, that you can use out of the box:

    1. redis - the default repository, stores logs in Redis.
    2. postgres - stores logs in a PostgreSQL database.
    3. cloudwatch - stores logs in AWS CloudWatch.

    You can also implement your own repository. To do this, you need to create a new class that inherits from the AbstractRepository class and implement all the required methods.

    See the abstract repository documentation and custom repository documentation for more information.

    "},{"location":"repositories/cloudwatch/","title":"Cloudwatch repository","text":""},{"location":"repositories/cloudwatch/#event_audit.repositories.cloudwatch.CloudWatchRepository.__init__","title":"__init__(credentials=None, log_group='/ckan/event-audit', log_stream='event-audit-stream')","text":"

    CloudWatch repository.

    PARAMETER DESCRIPTION credentials

    AWS credentials. If not provided, the extension configuration will be used.

    TYPE: AWSCredentials | None DEFAULT: None

    log_group

    CloudWatch log group name.

    TYPE: str DEFAULT: '/ckan/event-audit'

    log_stream

    CloudWatch log stream name.

    TYPE: str DEFAULT: 'event-audit-stream'

    "},{"location":"repositories/cloudwatch/#event_audit.repositories.cloudwatch.CloudWatchRepository.filter_events","title":"filter_events(filters)","text":"

    Filters events based on provided filter criteria.

    PARAMETER DESCRIPTION filters

    filters to apply.

    TYPE: Filters

    "},{"location":"repositories/cloudwatch/#event_audit.repositories.cloudwatch.CloudWatchRepository.get_event","title":"get_event(event_id)","text":"

    Retrieves a single event from the repository.

    PARAMETER DESCRIPTION event_id

    event ID.

    TYPE: str

    RETURNS DESCRIPTION Optional[Event]

    types.Event | None: event object or None if not found.

    "},{"location":"repositories/cloudwatch/#event_audit.repositories.cloudwatch.CloudWatchRepository.remove_all_events","title":"remove_all_events()","text":"

    Removes all events from the repository.

    RETURNS DESCRIPTION Result

    types.Result: result of the operation.

    "},{"location":"repositories/cloudwatch/#event_audit.repositories.cloudwatch.CloudWatchRepository.remove_event","title":"remove_event(event_id)","text":"

    Remove operation is not supported for CloudWatch logs.

    As of today, you cannot delete a single log event from CloudWatch log stream, the alternative will be using Lambda functions: set a Lambda function trigger, filter all logs, then write the remaining logs to a new log group/stream, then delete the original log stream.

    It's potentially too expensive to do this operation, so it's not implemented.

    Note

    The remove single event operation is not supported

    "},{"location":"repositories/cloudwatch/#event_audit.repositories.cloudwatch.CloudWatchRepository.remove_events","title":"remove_events(filters)","text":"

    See remove_event method docstring.

    "},{"location":"repositories/cloudwatch/#event_audit.repositories.cloudwatch.CloudWatchRepository.test_connection","title":"test_connection()","text":"

    Tests the connection to the repository.

    RETURNS DESCRIPTION bool

    whether the connection was successful.

    TYPE: bool

    "},{"location":"repositories/cloudwatch/#event_audit.repositories.cloudwatch.CloudWatchRepository.write_event","title":"write_event(event)","text":"

    Writes a single event to the repository.

    PARAMETER DESCRIPTION event

    event to write.

    TYPE: Event

    RETURNS DESCRIPTION Result

    types.Result: result of the operation.

    "},{"location":"repositories/custom/","title":"Custom","text":"

    Here you can see a naive example of how to implement a custom repository, that stores logs in a json file.

    from ckanext.event_audit.repositories import AbstractRepository\n\nclass FileRepository(AbstractRepository):\n    def __init__(self, file_path: str | None = None):\n        self.file_path = file_path or '/tmp/event_audit.json'\n\n    def log(self) -> str:\n        return \"file\"\n\n    def write_event(self, event: types.Event) -> types.Result:\n        with open(self.file_path, 'a') as f:\n            data = json.load(f)\n            data[event.id] = event.model_dump()\n\n            f.write(json.dumps(data))\n\n        return types.Result(success=True)\n\n    def get_event(self, event_id: Any) -> types.Event | None:\n        with open(self.file_path, 'r') as f:\n            data = json.load(f)\n\n            if event_id in data:\n                return types.Event.model_validate(data[event_id])\n\n        return None\n\n    def filter_events(self, filters: types.Filters) -> list[types.Event]:\n        with open(self.file_path, 'r') as f:\n            data = json.load(f)\n\n            result = []\n\n            for event in data.values():\n                if _match_filters(event, filters):\n                    result.append(types.Event.model_validate(event))\n\n            return result\n\n    def _match_filters(self, event: types.EventData, filters: types.Filters) -> bool:\n        ...\n\n    def test_connection(self) -> types.Result:\n        return types.Result(success=True)\n

    In this version, it doesn't implement the remove_event, remove_events and remove_all_events methods, but you can implement them in the same way as the other methods. If the repository able to remove one or multiple events, it must inherits from the respective class - RemoveSingle or RemoveAll. For example:

    import os\n\nfrom ckanext.event_audit.repositories import (\n    AbstractRepository,\n    RemoveSingle,\n    RemoveAll,\n    RemoveFiltered,\n)\n\n\nclass FileRepository(AbstractRepository, RemoveSingle, RemoveAll, RemoveFiltered):\n    ...\n\n    def remove_event(self, event_id: Any) -> types.Result:\n        with open(self.file_path, \"w\") as f:\n            data = json.load(f)\n\n            if event_id in data:\n                del data[event_id]\n                f.write(json.dumps(data))\n\n                return types.Result(success=True)\n\n        return types.Result(success=False, message=\"Event not found\")\n\n    def remove_events(self, filters: types.Filters) -> types.Result:\n        with open(self.file_path, \"w\") as f:\n            data = json.load(f)\n\n            for event_id, event in data.items():\n                if _match_filters(event, filters):\n                    del data[event_id]\n\n            f.write(json.dumps(data))\n\n        return types.Result(success=True)\n\n    def _match_filters(\n        self, event: types.EventData, filters: types.Filters\n    ) -> bool: ...\n\n    def remove_all_events(self, filters: types.Filters) -> types.Result:\n        \"\"\"Removes the file if exists.\"\"\"\n\n        if os.path.exists(self.file_path):\n            os.remove(self.file_path)\n\n        return types.Result(success=True)\n
    "},{"location":"repositories/postgres/","title":"Postgres repository","text":""},{"location":"repositories/postgres/#event_audit.repositories.postgres.PostgresRepository.filter_events","title":"filter_events(filters)","text":"

    Filters events based on provided filter criteria.

    PARAMETER DESCRIPTION filters

    filters to apply.

    TYPE: Filters

    RETURNS DESCRIPTION List[Event]

    List[types.Event]: list of events.

    "},{"location":"repositories/postgres/#event_audit.repositories.postgres.PostgresRepository.get_event","title":"get_event(event_id)","text":"

    Retrieves a single event from the repository.

    PARAMETER DESCRIPTION event_id

    event ID.

    TYPE: str

    RETURNS DESCRIPTION Event | None

    types.Event | None: event object or None if not found.

    "},{"location":"repositories/postgres/#event_audit.repositories.postgres.PostgresRepository.remove_all_events","title":"remove_all_events()","text":"

    Removes all events from the repository.

    RETURNS DESCRIPTION Result

    types.Result: result of the operation.

    "},{"location":"repositories/postgres/#event_audit.repositories.postgres.PostgresRepository.remove_event","title":"remove_event(event_id, session=None, defer_commit=False)","text":"

    Removes a single event from the repository.

    PARAMETER DESCRIPTION event_id

    event ID.

    TYPE: str

    session

    session to use.

    TYPE: Session | None DEFAULT: None

    defer_commit

    whether to defer the commit.

    TYPE: bool DEFAULT: False

    RETURNS DESCRIPTION Result

    types.Result: result of the operation.

    "},{"location":"repositories/postgres/#event_audit.repositories.postgres.PostgresRepository.remove_events","title":"remove_events(filters)","text":"

    Removes a filtered set of events from the repository.

    PARAMETER DESCRIPTION filters

    filters to apply.

    TYPE: Filters

    RETURNS DESCRIPTION Result

    types.Result: result of the operation.

    "},{"location":"repositories/postgres/#event_audit.repositories.postgres.PostgresRepository.test_connection","title":"test_connection()","text":"

    Tests the connection to the repository.

    RETURNS DESCRIPTION bool

    whether the connection was successful.

    TYPE: bool

    "},{"location":"repositories/postgres/#event_audit.repositories.postgres.PostgresRepository.write_event","title":"write_event(event, session=None, defer_commit=False)","text":"

    Writes a single event to the repository.

    PARAMETER DESCRIPTION event

    event to write.

    TYPE: Event

    session

    session to use.

    TYPE: Session | None DEFAULT: None

    defer_commit

    whether to defer the commit.

    TYPE: bool DEFAULT: False

    RETURNS DESCRIPTION Result

    types.Result: result of the operation.

    "},{"location":"repositories/postgres/#event_audit.repositories.postgres.PostgresRepository.write_events","title":"write_events(events)","text":"

    Write multiple events to the repository.

    PARAMETER DESCRIPTION events

    events to write.

    TYPE: Iterable[Event]

    RETURNS DESCRIPTION Result

    types.Result: result of the operation.

    "},{"location":"repositories/redis/","title":"Redis repository","text":""},{"location":"repositories/redis/#event_audit.repositories.redis.RedisRepository.filter_events","title":"filter_events(filters)","text":"

    Filters events based on patterns generated from the provided filters.

    PARAMETER DESCRIPTION filters

    filters to apply.

    TYPE: Filters

    "},{"location":"repositories/redis/#event_audit.repositories.redis.RedisRepository.get_event","title":"get_event(event_id)","text":"

    Get an event by its ID.

    PARAMETER DESCRIPTION event_id

    event ID.

    TYPE: float

    "},{"location":"repositories/redis/#event_audit.repositories.redis.RedisRepository.remove_all_events","title":"remove_all_events()","text":"

    Removes all events from the repository.

    RETURNS DESCRIPTION Result

    types.Result: result of the operation.

    "},{"location":"repositories/redis/#event_audit.repositories.redis.RedisRepository.remove_event","title":"remove_event(event_id)","text":"

    Removes an event by its ID.

    PARAMETER DESCRIPTION event_id

    event ID.

    TYPE: float

    RETURNS DESCRIPTION Result

    types.Result: result of the operation.

    "},{"location":"repositories/redis/#event_audit.repositories.redis.RedisRepository.remove_events","title":"remove_events(filters)","text":"

    Removes a filtered set of events from the repository.

    PARAMETER DESCRIPTION filters

    filters to apply.

    TYPE: Filters

    RETURNS DESCRIPTION Result

    types.Result: result of the operation.

    "},{"location":"repositories/redis/#event_audit.repositories.redis.RedisRepository.test_connection","title":"test_connection()","text":"

    Tests the connection to the repository.

    RETURNS DESCRIPTION bool

    whether the connection was successful.

    TYPE: bool

    "},{"location":"repositories/redis/#event_audit.repositories.redis.RedisRepository.write_event","title":"write_event(event)","text":"

    Writes an event to Redis.

    PARAMETER DESCRIPTION event

    event to write.

    TYPE: Event

    RETURNS DESCRIPTION Result

    types.Result: result of the operation.

    "}]} \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml index 0088bd6..0dc3a42 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -2,98 +2,94 @@ https://.github.io/ckanext-event-audit/ - 2024-11-19 + 2024-11-20 https://.github.io/ckanext-event-audit/cli/ - 2024-11-19 + 2024-11-20 https://.github.io/ckanext-event-audit/install/ - 2024-11-19 + 2024-11-20 https://.github.io/ckanext-event-audit/interfaces/ - 2024-11-19 + 2024-11-20 https://.github.io/ckanext-event-audit/usage/ - 2024-11-19 + 2024-11-20 https://.github.io/ckanext-event-audit/utils/ - 2024-11-19 + 2024-11-20 https://.github.io/ckanext-event-audit/validators/ - 2024-11-19 + 2024-11-20 https://.github.io/ckanext-event-audit/configure/active_repo/ - 2024-11-19 + 2024-11-20 https://.github.io/ckanext-event-audit/configure/async/ - 2024-11-19 + 2024-11-20 https://.github.io/ckanext-event-audit/configure/cloudwatch/ - 2024-11-19 + 2024-11-20 https://.github.io/ckanext-event-audit/configure/ignore/ - 2024-11-19 + 2024-11-20 https://.github.io/ckanext-event-audit/configure/tracking/ - 2024-11-19 + 2024-11-20 https://.github.io/ckanext-event-audit/exporters/basic/ - 2024-11-19 + 2024-11-20 https://.github.io/ckanext-event-audit/exporters/csv/ - 2024-11-19 + 2024-11-20 https://.github.io/ckanext-event-audit/exporters/json/ - 2024-11-19 + 2024-11-20 https://.github.io/ckanext-event-audit/exporters/tsv/ - 2024-11-19 + 2024-11-20 https://.github.io/ckanext-event-audit/exporters/xlsx/ - 2024-11-19 + 2024-11-20 https://.github.io/ckanext-event-audit/repositories/abstract/ - 2024-11-19 + 2024-11-20 https://.github.io/ckanext-event-audit/repositories/basic/ - 2024-11-19 + 2024-11-20 https://.github.io/ckanext-event-audit/repositories/cloudwatch/ - 2024-11-19 + 2024-11-20 https://.github.io/ckanext-event-audit/repositories/custom/ - 2024-11-19 + 2024-11-20 https://.github.io/ckanext-event-audit/repositories/postgres/ - 2024-11-19 + 2024-11-20 https://.github.io/ckanext-event-audit/repositories/redis/ - 2024-11-19 - - - https://.github.io/ckanext-event-audit/repositories/test/ - 2024-11-19 + 2024-11-20 \ No newline at end of file diff --git a/sitemap.xml.gz b/sitemap.xml.gz index 4d76e8d5db2d849819a7e2993ce161a8438ca831..438b76e642db119dfafe5691532ded3a98e0fdd7 100644 GIT binary patch delta 346 zcmV-g0j2)%0_*|@ABzYGfF?bW2OWR5+F_g0^tLD1&J!hG;+5bCJ0E-dk+z!Fa}VGP zA2R;`K(c}Axb!xgz%!CN4XKrb_?@TSp!e01>av zIb0plP+%FzhuX#Jq!~>D9EM7#1Sr0lTml%9#9=I!muMJk9S!dz@)#~xed0A`Bn_Il sDRYOCKzY6A8Cj@LgC%sO^%0+DcQhUvd;sOrgs(;Y3vQIw5sC}|0Fefr6951J delta 350 zcmV-k0ipiv0`LL{ABzYG0M$E@2OWQ=+F_m2^tLD1&J!hW;*~&zO_II+NLx+oxd-6F zhm8L}kZeqSTn3#@;0Ucb)Tnf>Jxy$&R7QtfUuM5 z5}uA|D6ovyh1^BrBnedl9Ewh+1Sr1AnglR7iOX0tEzvO6JR0gF>o7d7@S&1Oaz62o`|Gt7d|=7FNJ%*YZMIt07(a
    exporter_name + exporter_name +

    The name of the exporter to retrieve.

    @@ -1335,7 +1342,9 @@

    repo_name + repo_name +

    The name of the repository to retrieve.

    diff --git a/validators/index.html b/validators/index.html index cf4ea39..45213c4 100644 --- a/validators/index.html +++ b/validators/index.html @@ -18,7 +18,7 @@ - + @@ -1024,7 +1024,9 @@

    value + value +

    The repository name.

    @@ -1038,7 +1040,9 @@

    context + context +

    The CKAN context.