RSS allow access via token (#310)

Allow access via a token
* New RSS URL
* Redirect the old RSS feed URL
* fix tests
pull/312/head
dgtlmoon 3 years ago committed by GitHub
parent e71dbbe771
commit 9815fc2526
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -224,24 +224,23 @@ def changedetection_app(config=None, datastore_o=None):
# Disable password loginif there is not one set # Disable password loginif there is not one set
app.config['LOGIN_DISABLED'] = datastore.data['settings']['application']['password'] == False app.config['LOGIN_DISABLED'] = datastore.data['settings']['application']['password'] == False
@app.route("/", methods=['GET']) # For the RSS path, allow access via a token
if request.path == '/rss' and request.args.get('token'):
app_rss_token = datastore.data['settings']['application']['rss_access_token']
rss_url_token = request.args.get('token')
if app_rss_token == rss_url_token:
app.config['LOGIN_DISABLED'] = True
@app.route("/rss", methods=['GET'])
@login_required @login_required
def index(): def rss():
limit_tag = request.args.get('tag')
pause_uuid = request.args.get('pause')
if pause_uuid:
try:
datastore.data['watching'][pause_uuid]['paused'] ^= True
datastore.needs_write = True
return redirect(url_for('index', tag = limit_tag))
except KeyError:
pass
limit_tag = request.args.get('tag')
# Sort by last_changed and add the uuid which is usually the key.. # Sort by last_changed and add the uuid which is usually the key..
sorted_watches = [] sorted_watches = []
# @todo needs a .itemsWithTag() or something
for uuid, watch in datastore.data['watching'].items(): for uuid, watch in datastore.data['watching'].items():
if limit_tag != None: if limit_tag != None:
@ -258,10 +257,6 @@ def changedetection_app(config=None, datastore_o=None):
sorted_watches.sort(key=lambda x: x['last_changed'], reverse=True) sorted_watches.sort(key=lambda x: x['last_changed'], reverse=True)
existing_tags = datastore.get_all_tags()
rss = request.args.get('rss')
if rss:
fg = FeedGenerator() fg = FeedGenerator()
fg.title('changedetection.io') fg.title('changedetection.io')
fg.description('Feed description') fg.description('Feed description')
@ -285,7 +280,45 @@ def changedetection_app(config=None, datastore_o=None):
response.headers.set('Content-Type', 'application/rss+xml') response.headers.set('Content-Type', 'application/rss+xml')
return response return response
@app.route("/", methods=['GET'])
@login_required
def index():
limit_tag = request.args.get('tag')
pause_uuid = request.args.get('pause')
# Redirect for the old rss path which used the /?rss=true
if request.args.get('rss'):
return redirect(url_for('rss', tag=limit_tag))
if pause_uuid:
try:
datastore.data['watching'][pause_uuid]['paused'] ^= True
datastore.needs_write = True
return redirect(url_for('index', tag = limit_tag))
except KeyError:
pass
# Sort by last_changed and add the uuid which is usually the key..
sorted_watches = []
for uuid, watch in datastore.data['watching'].items():
if limit_tag != None:
# Support for comma separated list of tags.
for tag_in_watch in watch['tag'].split(','):
tag_in_watch = tag_in_watch.strip()
if tag_in_watch == limit_tag:
watch['uuid'] = uuid
sorted_watches.append(watch)
else: else:
watch['uuid'] = uuid
sorted_watches.append(watch)
sorted_watches.sort(key=lambda x: x['last_changed'], reverse=True)
existing_tags = datastore.get_all_tags()
from changedetectionio import forms from changedetectionio import forms
form = forms.quickWatchForm(request.form) form = forms.quickWatchForm(request.form)
@ -294,6 +327,7 @@ def changedetection_app(config=None, datastore_o=None):
watches=sorted_watches, watches=sorted_watches,
tags=existing_tags, tags=existing_tags,
active_tag=limit_tag, active_tag=limit_tag,
app_rss_token=datastore.data['settings']['application']['rss_access_token'],
has_unviewed=datastore.data['has_unviewed']) has_unviewed=datastore.data['has_unviewed'])
return output return output

@ -49,7 +49,7 @@ class ChangeDetectionStore:
# Custom notification content # Custom notification content
'notification_title': None, 'notification_title': None,
'notification_body': None, 'notification_body': None,
'notification_format': None, 'notification_format': None
} }
} }
} }
@ -147,6 +147,12 @@ class ChangeDetectionStore:
else: else:
self.__data['app_guid'] = str(uuid_builder.uuid4()) self.__data['app_guid'] = str(uuid_builder.uuid4())
# Generate the URL access token for RSS feeds
if not 'rss_access_token' in self.__data['settings']['application']:
import secrets
secret = secrets.token_hex(16)
self.__data['settings']['application']['rss_access_token'] = secret
self.needs_write = True self.needs_write = True
# Finally start the thread that will manage periodic data saves to JSON # Finally start the thread that will manage periodic data saves to JSON

@ -92,7 +92,7 @@
all {% if active_tag%}in "{{active_tag}}"{%endif%}</a> all {% if active_tag%}in "{{active_tag}}"{%endif%}</a>
</li> </li>
<li> <li>
<a href="{{ url_for('index', tag=active_tag , rss=true)}}"><img id="feed-icon" src="{{url_for('static_content', group='images', filename='Generic_Feed-icon.svg')}}" height="15px"></a> <a href="{{ url_for('rss', tag=active_tag , token=app_rss_token)}}"><img id="feed-icon" src="{{url_for('static_content', group='images', filename='Generic_Feed-icon.svg')}}" height="15px"></a>
</li> </li>
</ul> </ul>
</div> </div>

@ -59,7 +59,7 @@ def test_check_basic_change_detection_functionality(client, live_server):
assert b'unviewed' in res.data assert b'unviewed' in res.data
# #75, and it should be in the RSS feed # #75, and it should be in the RSS feed
res = client.get(url_for("index", rss="true")) res = client.get(url_for("rss"))
expected_url = url_for('test_endpoint', _external=True) expected_url = url_for('test_endpoint', _external=True)
assert b'<rss' in res.data assert b'<rss' in res.data
assert expected_url.encode('utf-8') in res.data assert expected_url.encode('utf-8') in res.data

Loading…
Cancel
Save