-
Notifications
You must be signed in to change notification settings - Fork 10
Webhooks cann't trigger AppAPI events #355
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Note: Line 9 in 1e667d4
|
webhooks_listener code that calls ExApp is located here: |
I can check this later with your example(will try today, but can't promise), we currently use this only in |
I checked my code and the nextcloud responses. Here the code. import pathlib
import time
import traceback
import requests
from contextlib import asynccontextmanager
from fastapi import FastAPI, BackgroundTasks
from nc_py_api import NextcloudApp
from nc_py_api.ex_app import AppAPIAuthMiddleware, LogLvl, run_app, set_handlers, nc_app
from fastapi import Depends
from typing import Annotated
LOG_LOCAL_HOST_STRING = "127.0.0.1"
WEBHOOK_HOST = "" # "http://127.0.0.1:2981"
possible_note_events = [
"OCA\\Forms\\Events\\FormSubmittedEvent",
"OCA\\Tables\\Event\\RowAddedEvent",
"OCA\\Tables\\Event\\RowDeletedEvent",
"OCA\\Tables\\Event\\RowUpdatedEvent",
"OCP\\Calendar\\Events\\CalendarObjectCreatedEvent",
"OCP\\Calendar\\Events\\CalendarObjectDeletedEvent",
"OCP\\Calendar\\Events\\CalendarObjectMovedEvent",
"OCP\\Calendar\\Events\\CalendarObjectMovedToTrashEvent",
"OCP\\Calendar\\Events\\CalendarObjectRestoredEvent",
"OCP\\Calendar\\Events\\CalendarObjectUpdatedEvent",
"OCP\\Files\\Events\\Node\\BeforeNodeCreatedEvent",
"OCP\\Files\\Events\\Node\\BeforeNodeTouchedEvent",
"OCP\\Files\\Events\\Node\\BeforeNodeWrittenEvent",
"OCP\\Files\\Events\\Node\\BeforeNodeReadEvent",
"OCP\\Files\\Events\\Node\\BeforeNodeDeletedEvent",
"OCP\\Files\\Events\\Node\\NodeCreatedEvent",
"OCP\\Files\\Events\\Node\\NodeTouchedEvent",
"OCP\\Files\\Events\\Node\\NodeWrittenEvent",
"OCP\\Files\\Events\\Node\\NodeDeletedEvent",
"OCP\\Files\\Events\\Node\\NodeCopiedEvent",
# "OCP\\Files\\Events\\Node\\NodeRestoredEvent",
"OCP\\Files\\Events\\Node\\NodeRenamedEvent",
"OCP\\Files\\Events\\Node\\BeforeNodeCopiedEvent",
# "OCP\\Files\\Events\\Node\\BeforeNodeRestoredEvent",
"OCP\\Files\\Events\\Node\\BeforeNodeRenamedEvent",
"OCP\\SystemTag\\MapperEvent"
]
def file_event_handler(event_data: dict, nc: NextcloudApp):
try:
pass
except Exception as e:
error_string = 'Exception:\n', traceback.format_exc() + "\n" + str(e)
response = requests.post(f"http://{LOG_LOCAL_HOST_STRING}:2998/log_string", json={"error": str(error_string)})
nc.log(LogLvl.ERROR, f"Error: {error_string}")
raise e
@asynccontextmanager
async def lifespan(app: FastAPI):
set_handlers(app, enabled_handler)
yield
APP = FastAPI(lifespan=lifespan)
APP.add_middleware(AppAPIAuthMiddleware)
@APP.post("/basic_file_checker")
async def basic_file_checker(
event_data: dict,
# files: ActionFileInfoEx,
nc: Annotated[NextcloudApp, Depends(nc_app)],
background_tasks: BackgroundTasks,
):
response = requests.post(f"http://{LOG_LOCAL_HOST_STRING}:2998/log_string",
json={"ID": "basic_file_checker", "called": "true", "data": event_data})
background_tasks.add_task(file_event_handler, event_data, nc)
def enabled_handler(enabled: bool, nc: NextcloudApp) -> str:
print(f"enabled={enabled}")
response = requests.post(f"http://{LOG_LOCAL_HOST_STRING}:2998/log_string",
json={"ID": "enabled_handler", "enabled": enabled})
try:
if enabled:
event_list = [
#"OCP\\Files\\Events\\Node\\BeforeNodeCreatedEvent",
"OCP\\Files\\Events\\Node\\NodeCreatedEvent",
#"OCP\\Files\\Events\\Node\\BeforeNodeTouchedEvent",
"OCP\\Files\\Events\\Node\\NodeTouchedEvent",
#"OCP\\Files\\Events\\Node\\BeforeNodeWrittenEvent",
"OCP\\Files\\Events\\Node\\NodeWrittenEvent",
#"OCP\\Files\\Events\\Node\\BeforeNodeReadEvent",
#"OCP\\Files\\Events\\Node\\BeforeNodeDeletedEvent",
"OCP\\Files\\Events\\Node\\NodeDeletedEvent",
#"OCP\\Files\\Events\\Node\\BeforeNodeCopiedEvent",
"OCP\\Files\\Events\\Node\\NodeCopiedEvent",
#"OCP\\Files\\Events\\Node\\BeforeNodeRenamedEvent",
"OCP\\Files\\Events\\Node\\NodeRenamedEvent",
]
for event_item in event_list:
if not event_item.startswith("OCP\\Files\\Events\\Node\\"):
continue
nc.webhooks.register(
http_method="POST",
uri=f"{WEBHOOK_HOST}/basic_file_checker",
event=event_item
)
# nc.events_listener.register(
# event_type="node_event",
# callback_url="/basic_file_checker"
# # event_subtypes=[
# # "NodeWrittenEvent",
# # "NodeCreatedEvent",
# # "NodeTouchedEvent",
# # "NodeRenamedEvent",
# # "NodeCopiedEvent",
# # "NodeDeletedEvent",
# # ]
# )
# https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-files-events-node-nodecreatedevent
# FileChecker.create_nc_tags(nc=nc)
wh_list = nc.webhooks.get_list()
wh_list = [i.__dict__ for i in wh_list]
response = requests.post(f"http://{LOG_LOCAL_HOST_STRING}:2998/log_string",
json={"id": "webhook list", "data": wh_list})
nc.log(LogLvl.INFO, f"App enabled: {enabled}")
except Exception as e:
error_string = 'Exception:\n', traceback.format_exc() + "\n" + str(e)
response = requests.post(f"http://{LOG_LOCAL_HOST_STRING}:2998/log_string", json={"error": error_string})
nc.log(LogLvl.ERROR, f"Error: {error_string}")
return ""
if __name__ == "__main__":
pathlib.Path("temp").mkdir(parents=True, exist_ok=True)
run_app(
"main:APP",
log_level="trace",
)
|
I found the problem again @bigcat88 The webhook call has no permissions def file_event_handler(event_data: dict, nc: NextcloudApp):
try:
nc_file = nc.files.by_id(str(event_data["event"]["node"]["id"]))
except Exception as e:
error_string = 'Exception:\n', traceback.format_exc() + "\n" + str(e)
response = requests.post(f"http://{LOG_LOCAL_HOST_STRING}:2998/log_string", json={"error": str(error_string)})
nc.log(LogLvl.ERROR, f"Error: {error_string}")
raise e
|
Do not understand how that is possible.
Will take a look at this |
I modifed your example a bit, and I see that Is I understand that this is the issue? Edited: if yes, that this is not an issue. webhooks_listeners has specific check condition: if ($exAppId !== null && str_starts_with($webhookUri, '/'))
This is done for several reasons(from memory, afaik):
|
It is some kind of auth problem, but I don't know from where.
The check for the "/" at the start makes sense. For that reason, I changed the To be sure. I tested it with this code for the register and got the same error.
Here the whole cleaned up code. import pathlib
import traceback
import requests
from contextlib import asynccontextmanager
from fastapi import FastAPI, BackgroundTasks
from nc_py_api import NextcloudApp
from nc_py_api.ex_app import AppAPIAuthMiddleware, LogLvl, run_app, set_handlers, nc_app
from fastapi import Depends
from typing import Annotated
LOG_LOCAL_HOST_STRING = "127.0.0.1"
def file_event_handler(event_data: dict, nc: NextcloudApp):
try:
nc_file = nc.files.by_id(str(event_data["event"]["node"]["id"]))
except Exception as e:
error_string = 'Exception:\n', traceback.format_exc() + "\n" + str(e)
response = requests.post(f"http://{LOG_LOCAL_HOST_STRING}:2998/log_string", json={"error": str(error_string)})
nc.log(LogLvl.ERROR, f"Error: {error_string}")
raise e
@asynccontextmanager
async def lifespan(app: FastAPI):
set_handlers(app, enabled_handler)
yield
APP = FastAPI(lifespan=lifespan)
APP.add_middleware(AppAPIAuthMiddleware)
@APP.post("/basic_file_checker")
async def basic_file_checker(
event_data: dict,
# files: ActionFileInfoEx,
nc: Annotated[NextcloudApp, Depends(nc_app)],
background_tasks: BackgroundTasks,
):
response = requests.post(f"http://{LOG_LOCAL_HOST_STRING}:2998/log_string",
json={"ID": "basic_file_checker", "called": "true", "data": event_data})
background_tasks.add_task(file_event_handler, event_data, nc)
def enabled_handler(enabled: bool, nc: NextcloudApp) -> str:
print(f"enabled={enabled}")
response = requests.post(f"http://{LOG_LOCAL_HOST_STRING}:2998/log_string",
json={"ID": "enabled_handler", "enabled": enabled})
try:
if enabled:
event_list = [
"OCP\\Files\\Events\\Node\\NodeCreatedEvent",
"OCP\\Files\\Events\\Node\\NodeTouchedEvent",
"OCP\\Files\\Events\\Node\\NodeWrittenEvent",
"OCP\\Files\\Events\\Node\\NodeDeletedEvent",
"OCP\\Files\\Events\\Node\\NodeCopiedEvent",
"OCP\\Files\\Events\\Node\\NodeRenamedEvent",
]
for event_item in event_list:
if not event_item.startswith("OCP\\Files\\Events\\Node\\"):
continue
nc.webhooks.register(
http_method="POST",
uri="/basic_file_checker",
event=event_item
)
wh_list = nc.webhooks.get_list()
wh_list = [i.__dict__ for i in wh_list]
response = requests.post(f"http://{LOG_LOCAL_HOST_STRING}:2998/log_string",
json={"id": "webhook list", "data": wh_list})
nc.log(LogLvl.INFO, f"App enabled: {enabled}")
except Exception as e:
error_string = 'Exception:\n', traceback.format_exc() + "\n" + str(e)
response = requests.post(f"http://{LOG_LOCAL_HOST_STRING}:2998/log_string", json={"error": error_string})
nc.log(LogLvl.ERROR, f"Error: {error_string}")
return ""
if __name__ == "__main__":
pathlib.Path("temp").mkdir(parents=True, exist_ok=True)
run_app(
"main:APP",
log_level="trace",
)
|
Please ,post the content of I guess the field |
Content of wh_list = nc.webhooks.get_list()
wh_list = [i.__dict__ for i in wh_list] [
{
"_raw_data": {
"id": 404,
"appId": "basic_file_checker",
"userId": null,
"httpMethod": "POST",
"uri": "/basic_file_checker",
"event": "OCP\\Files\\Events\\Node\\NodeCreatedEvent",
"eventFilter": [],
"userIdFilter": "",
"headers": null,
"authMethod": "none",
"authData": null
}
},
{
"_raw_data": {
"id": 405,
"appId": "basic_file_checker",
"userId": null,
"httpMethod": "POST",
"uri": "/basic_file_checker",
"event": "OCP\\Files\\Events\\Node\\NodeTouchedEvent",
"eventFilter": [],
"userIdFilter": "",
"headers": null,
"authMethod": "none",
"authData": null
}
},
{
"_raw_data": {
"id": 406,
"appId": "basic_file_checker",
"userId": null,
"httpMethod": "POST",
"uri": "/basic_file_checker",
"event": "OCP\\Files\\Events\\Node\\NodeWrittenEvent",
"eventFilter": [],
"userIdFilter": "",
"headers": null,
"authMethod": "none",
"authData": null
}
},
{
"_raw_data": {
"id": 407,
"appId": "basic_file_checker",
"userId": null,
"httpMethod": "POST",
"uri": "/basic_file_checker",
"event": "OCP\\Files\\Events\\Node\\NodeDeletedEvent",
"eventFilter": [],
"userIdFilter": "",
"headers": null,
"authMethod": "none",
"authData": null
}
},
{
"_raw_data": {
"id": 408,
"appId": "basic_file_checker",
"userId": null,
"httpMethod": "POST",
"uri": "/basic_file_checker",
"event": "OCP\\Files\\Events\\Node\\NodeCopiedEvent",
"eventFilter": [],
"userIdFilter": "",
"headers": null,
"authMethod": "none",
"authData": null
}
},
{
"_raw_data": {
"id": 409,
"appId": "basic_file_checker",
"userId": null,
"httpMethod": "POST",
"uri": "/basic_file_checker",
"event": "OCP\\Files\\Events\\Node\\NodeRenamedEvent",
"eventFilter": [],
"userIdFilter": "",
"headers": null,
"authMethod": "none",
"authData": null
}
}
] |
thanks, I will try to reproduce this today |
I triaged this in a little bit more than a hour... Exception To make it work now you can add such code: def file_event_handler(event_data: dict, nc: NextcloudApp):
nc.set_user(event_data["user"]["uid"]) # **Add this line**
try:
nc_file = nc.files.by_id(str(event_data["event"]["node"]["id"]))
print(nc_file)
except Exception as e:
error_string = 'Exception:\n', traceback.format_exc() + "\n" + str(e)
nc.log(LogLvl.ERROR, f"Error: {error_string}")
raise e Feel free to create issue(potential bug or feature request from blank issue) in AppAPI repo regarding this, maybe it can be fixed/improved, as here we see that user gets filled: but here is used value from the |
I checked the solution and it works. I can add a simple version of my code to the example for future reference. |
I looked through the documentation, and can't find a solution.
Problem
The AppAPI docker image in the example is using an secret for connecting to the docker image.
Without adding a auth_method, a webhook can be registered but raise an error after the first call.
I can't find an example for a webhook call with an auth_method (or guess the name of the auth_method)
Steps/Code to Reproduce
same setup as #352
Python script in
lib/main.py
after that, make an edit in a file.
The text was updated successfully, but these errors were encountered: