feat: add in a doctype to optionally track API Requests (#32622)
This commit is contained in:
parent
d5518fde79
commit
1a3602f715
10 changed files with 156 additions and 2 deletions
|
|
@ -41,6 +41,17 @@ def handle(request: Request):
|
|||
`DELETE` will delete
|
||||
"""
|
||||
|
||||
if frappe.get_system_settings("log_api_requests"):
|
||||
doc = frappe.get_doc(
|
||||
{
|
||||
"doctype": "API Request Log",
|
||||
"path": request.path,
|
||||
"user": frappe.session.user,
|
||||
"method": request.method,
|
||||
}
|
||||
)
|
||||
doc.deferred_insert()
|
||||
|
||||
try:
|
||||
endpoint, arguments = API_URL_MAP.bind_to_environ(request.environ).match()
|
||||
except NotFound: # Wrap 404 - backward compatiblity
|
||||
|
|
|
|||
0
frappe/core/doctype/api_request_log/__init__.py
Normal file
0
frappe/core/doctype/api_request_log/__init__.py
Normal file
8
frappe/core/doctype/api_request_log/api_request_log.js
Normal file
8
frappe/core/doctype/api_request_log/api_request_log.js
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
// Copyright (c) 2025, Frappe Technologies and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
// frappe.ui.form.on("API Request Log", {
|
||||
// refresh(frm) {
|
||||
|
||||
// },
|
||||
// });
|
||||
62
frappe/core/doctype/api_request_log/api_request_log.json
Normal file
62
frappe/core/doctype/api_request_log/api_request_log.json
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
{
|
||||
"actions": [],
|
||||
"allow_rename": 1,
|
||||
"creation": "2025-05-21 16:51:56.070193",
|
||||
"doctype": "DocType",
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"path",
|
||||
"method",
|
||||
"user"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "path",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 1,
|
||||
"label": "Path"
|
||||
},
|
||||
{
|
||||
"fieldname": "user",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 1,
|
||||
"label": "User",
|
||||
"options": "User"
|
||||
},
|
||||
{
|
||||
"fieldname": "method",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 1,
|
||||
"label": "Method"
|
||||
}
|
||||
],
|
||||
"grid_page_length": 50,
|
||||
"index_web_pages_for_search": 1,
|
||||
"links": [],
|
||||
"modified": "2025-05-21 17:09:55.054044",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Core",
|
||||
"name": "API Request Log",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"row_format": "Dynamic",
|
||||
"sort_field": "creation",
|
||||
"sort_order": "DESC",
|
||||
"states": []
|
||||
}
|
||||
28
frappe/core/doctype/api_request_log/api_request_log.py
Normal file
28
frappe/core/doctype/api_request_log/api_request_log.py
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
# Copyright (c) 2025, Frappe Technologies and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
|
||||
class APIRequestLog(Document):
|
||||
# begin: auto-generated types
|
||||
# This code is auto-generated. Do not modify anything in this block.
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from frappe.types import DF
|
||||
|
||||
method: DF.Data | None
|
||||
path: DF.Data | None
|
||||
user: DF.Link | None
|
||||
# end: auto-generated types
|
||||
|
||||
@staticmethod
|
||||
def clear_old_logs(days: int = 90):
|
||||
from frappe.query_builder import Interval
|
||||
from frappe.query_builder.functions import Now
|
||||
|
||||
table = frappe.qb.DocType("API Request Log")
|
||||
frappe.db.delete(table, filters=(table.creation < (Now() - Interval(days=days))))
|
||||
29
frappe/core/doctype/api_request_log/test_api_request_log.py
Normal file
29
frappe/core/doctype/api_request_log/test_api_request_log.py
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
# Copyright (c) 2025, Frappe Technologies and Contributors
|
||||
# See license.txt
|
||||
|
||||
# import frappe
|
||||
from frappe.tests import IntegrationTestCase, UnitTestCase
|
||||
|
||||
# On IntegrationTestCase, the doctype test records and all
|
||||
# link-field test record dependencies are recursively loaded
|
||||
# Use these module variables to add/remove to/from that list
|
||||
EXTRA_TEST_RECORD_DEPENDENCIES = [] # eg. ["User"]
|
||||
IGNORE_TEST_RECORD_DEPENDENCIES = [] # eg. ["User"]
|
||||
|
||||
|
||||
class UnitTestAPIRequestLog(UnitTestCase):
|
||||
"""
|
||||
Unit tests for APIRequestLog.
|
||||
Use this class for testing individual functions and methods.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class IntegrationTestAPIRequestLog(IntegrationTestCase):
|
||||
"""
|
||||
Integration tests for APIRequestLog.
|
||||
Use this class for testing interactions between multiple components.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
|
@ -155,6 +155,7 @@ LOG_DOCTYPES = [
|
|||
"Email Queue Recipient",
|
||||
"Error Log",
|
||||
"OAuth Bearer Token",
|
||||
"API Request Log",
|
||||
]
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -104,7 +104,9 @@
|
|||
"allow_error_traceback",
|
||||
"enable_telemetry",
|
||||
"search_section",
|
||||
"link_field_results_limit"
|
||||
"link_field_results_limit",
|
||||
"api_logging_section",
|
||||
"log_api_requests"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
|
|
@ -707,12 +709,23 @@
|
|||
"fieldname": "max_report_rows",
|
||||
"fieldtype": "Int",
|
||||
"label": "Max Report Rows"
|
||||
},
|
||||
{
|
||||
"fieldname": "api_logging_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "API Logging"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "log_api_requests",
|
||||
"fieldtype": "Check",
|
||||
"label": "Log API Requests"
|
||||
}
|
||||
],
|
||||
"icon": "fa fa-cog",
|
||||
"issingle": 1,
|
||||
"links": [],
|
||||
"modified": "2025-05-19 14:17:40.748786",
|
||||
"modified": "2025-05-21 17:03:23.310169",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Core",
|
||||
"name": "System Settings",
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ class SystemSettings(Document):
|
|||
language: DF.Link
|
||||
lifespan_qrcode_image: DF.Int
|
||||
link_field_results_limit: DF.Int
|
||||
log_api_requests: DF.Check
|
||||
login_with_email_link: DF.Check
|
||||
login_with_email_link_expiry: DF.Int
|
||||
logout_on_password_reset: DF.Check
|
||||
|
|
|
|||
|
|
@ -569,6 +569,7 @@ default_log_clearing_doctypes = {
|
|||
"Activity Log": 90,
|
||||
"Route History": 90,
|
||||
"OAuth Bearer Token": 30,
|
||||
"API Request Log": 90,
|
||||
}
|
||||
|
||||
# These keys will not be erased when doing frappe.clear_cache()
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue