Compare commits

..

1 Commits

Author SHA1 Message Date
dgtlmoon
a7c1928c0f Small fix for when last fetched was zero bytes 2025-03-28 15:13:47 +01:00
8 changed files with 23 additions and 23 deletions

View File

@@ -19,6 +19,7 @@ from changedetectionio import store
from changedetectionio.flask_app import changedetection_app
from loguru import logger
# Only global so we can access it in the signal handler
app = None
datastore = None
@@ -28,6 +29,8 @@ def get_version():
# Parent wrapper or OS sends us a SIGTERM/SIGINT, do everything required for a clean shutdown
def sigshutdown_handler(_signo, _stack_frame):
global app
global datastore
name = signal.Signals(_signo).name
logger.critical(f'Shutdown: Got Signal - {name} ({_signo}), Saving DB to disk and calling shutdown')
datastore.sync_to_json()

View File

@@ -20,7 +20,10 @@ def login_optionally_required(func):
has_password_enabled = datastore.data['settings']['application'].get('password') or os.getenv("SALTED_PASS", False)
# Permitted
if request.endpoint and 'diff_history_page' in request.endpoint and datastore.data['settings']['application'].get('shared_diff_access'):
if request.endpoint and 'static_content' in request.endpoint and request.view_args and request.view_args.get('group') == 'styles':
return func(*args, **kwargs)
# Permitted
elif request.endpoint and 'diff_history_page' in request.endpoint and datastore.data['settings']['application'].get('shared_diff_access'):
return func(*args, **kwargs)
elif request.method in flask_login.config.EXEMPT_METHODS:
return func(*args, **kwargs)

View File

@@ -23,6 +23,7 @@ from loguru import logger
browsersteps_sessions = {}
io_interface_context = None
import json
import base64
import hashlib
from flask import Response
@@ -33,8 +34,10 @@ def construct_blueprint(datastore: ChangeDetectionStore):
from . import nonContext
from . import browser_steps
import time
global browsersteps_sessions
global io_interface_context
# We keep the playwright session open for many minutes
keepalive_seconds = int(os.getenv('BROWSERSTEPS_MINUTES_KEEPALIVE', 10)) * 60
@@ -101,6 +104,8 @@ def construct_blueprint(datastore: ChangeDetectionStore):
# A new session was requested, return sessionID
import uuid
global browsersteps_sessions
browsersteps_session_id = str(uuid.uuid4())
watch_uuid = request.args.get('uuid')
@@ -144,6 +149,7 @@ def construct_blueprint(datastore: ChangeDetectionStore):
def browsersteps_ui_update():
import base64
import playwright._impl._errors
global browsersteps_sessions
from changedetectionio.blueprint.browser_steps import browser_steps
remaining =0

View File

@@ -233,8 +233,7 @@ def changedetection_app(config=None, datastore_o=None):
if has_password_enabled and not flask_login.current_user.is_authenticated:
# Permitted
if request.endpoint and request.endpoint == 'static_content' and request.view_args:
# Handled by static_content handler
if request.endpoint and request.endpoint == 'static_content' and request.view_args and request.view_args.get('group') in ['styles', 'js', 'images', 'favicons']:
return None
# Permitted
elif request.endpoint and 'login' in request.endpoint:
@@ -352,15 +351,11 @@ def changedetection_app(config=None, datastore_o=None):
@app.route("/static/<string:group>/<string:filename>", methods=['GET'])
def static_content(group, filename):
from flask import make_response
import re
group = re.sub(r'[^\w.-]+', '', group.lower())
filename = re.sub(r'[^\w.-]+', '', filename.lower())
if group == 'screenshot':
# Could be sensitive, follow password requirements
if datastore.data['settings']['application']['password'] and not flask_login.current_user.is_authenticated:
if not datastore.data['settings']['application'].get('shared_diff_access'):
abort(403)
abort(403)
screenshot_filename = "last-screenshot.png" if not request.args.get('error_screenshot') else "last-error-screenshot.png"
@@ -409,7 +404,7 @@ def changedetection_app(config=None, datastore_o=None):
# These files should be in our subdirectory
try:
return send_from_directory(f"static/{group}", path=filename)
return send_from_directory("static/{}".format(group), path=filename)
except FileNotFoundError:
abort(404)

View File

@@ -307,7 +307,7 @@ Math: {{ 1 + 1 }}") }}
<div class="pure-form-message-inline">
<p id="verify-state-text">Use the verify (✓) button to test if a condition passes against the current snapshot.</p>
Read a quick tutorial about <a href="https://changedetection.io/tutorial/conditional-actions-web-page-changes">using conditional web page changes here</a>.<br>
Did you know that <strong>conditions</strong> can be extended with your own custom plugin? tutorials coming soon!<br>
</div>
</div>
</div>
@@ -337,7 +337,7 @@ xpath://body/div/span[contains(@class, 'example-class')]",
{% if '/text()' in field %}
<span class="pure-form-message-inline"><strong>Note!: //text() function does not work where the &lt;element&gt; contains &lt;![CDATA[]]&gt;</strong></span><br>
{% endif %}
<span class="pure-form-message-inline">One CSS, xPath 1 &amp; 2, JSON Path/JQ selector per line, <i>any</i> rules that matches will be used.<br>
<span class="pure-form-message-inline">One CSS, xPath, JSON Path/JQ selector per line, <i>any</i> rules that matches will be used.<br>
<span data-target="#advanced-help-selectors" class="toggle-show pure-button button-tag button-xsmall">Show advanced help and tips</span><br>
<ul id="advanced-help-selectors" style="display: none;">
<li>CSS - Limit text to this CSS rule, only text matching this CSS rule is included.</li>

View File

@@ -25,6 +25,7 @@ def test_setup(live_server):
def get_last_message_from_smtp_server():
import socket
global smtp_test_server
port = 11080 # socket server port number
client_socket = socket.socket() # instantiate
@@ -43,6 +44,7 @@ def test_check_notification_email_formats_default_HTML(client, live_server, meas
# live_server_setup(live_server)
set_original_response()
global smtp_test_server
notification_url = f'mailto://changedetection@{smtp_test_server}:11025/?to=fff@home.com'
#####################
@@ -97,6 +99,7 @@ def test_check_notification_email_formats_default_Text_override_HTML(client, liv
# https://github.com/caronc/apprise/issues/633
set_original_response()
global smtp_test_server
notification_url = f'mailto://changedetection@{smtp_test_server}:11025/?to=fff@home.com'
notification_body = f"""<!DOCTYPE html>
<html lang="en">

View File

@@ -60,11 +60,6 @@ def test_check_access_control(app, client, live_server):
res = c.get(url_for('static_content', group='styles', filename='404-testetest.css'))
assert res.status_code == 404
# Access to screenshots should be limited by 'shared_diff_access'
path = url_for('static_content', group='screenshot', filename='random-uuid-that-will-404.png', _external=True)
res = c.get(path)
assert res.status_code == 404
# Check wrong password does not let us in
res = c.post(
url_for("login"),
@@ -168,7 +163,7 @@ def test_check_access_control(app, client, live_server):
url_for("settings.settings_page"),
data={"application-password": "foobar",
# Should be disabled
"application-shared_diff_access": "",
# "application-shared_diff_access": "True",
"requests-time_between_check-minutes": 180,
'application-fetch_backend': "html_requests"},
follow_redirects=True
@@ -181,10 +176,6 @@ def test_check_access_control(app, client, live_server):
# Should be logged out
assert b"Login" in res.data
# Access to screenshots should be limited by 'shared_diff_access'
res = c.get(url_for('static_content', group='screenshot', filename='random-uuid-that-will-403.png'))
assert res.status_code == 403
# The diff page should return something valid when logged out
res = c.get(url_for("ui.ui_views.diff_history_page", uuid="first"))
assert b'Random content' not in res.data

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env python3
import json
import time
import urllib
from flask import url_for
from .util import live_server_setup, wait_for_all_checks
@@ -113,7 +113,6 @@ def test_conditions_with_text_and_number(client, live_server):
client.get(url_for("ui.form_watch_checknow"), follow_redirects=True)
wait_for_all_checks(client)
time.sleep(2)
# 75 is > 20 and < 100 and contains "5"
res = client.get(url_for("watchlist.index"))
assert b'unviewed' in res.data