Add option to share bookmarks publicly (#503)

* Make shared view public, add user profile fallback

* Allow unauthenticated access to shared bookmarks API

* Link shared bookmarks in unauthenticated layout

* Add public sharing setting

* Only show shared bookmarks link if there are publicly shared bookmarks

* Disable public sharing if sharing is disabled

* Show specific helper text when public sharing is enabled

* Fix tests

* Add more tests

* Improve setting description
This commit is contained in:
Sascha Ißbrücker
2023-08-15 00:20:52 +02:00
committed by GitHub
parent 22e8750c24
commit ea240eefd9
29 changed files with 667 additions and 87 deletions

View File

@@ -1,7 +1,7 @@
{% load static %}
{% load shared %}
{% load pagination %}
<ul class="bookmark-list{% if request.user.profile.permanent_notes %} show-notes{% endif %}">
<ul class="bookmark-list{% if request.user_profile.permanent_notes %} show-notes{% endif %}">
{% for bookmark in bookmarks %}
<li data-is-bookmark-item>
<label class="form-checkbox bulk-edit-toggle">
@@ -11,13 +11,13 @@
<div class="title">
<a href="{{ bookmark.url }}" target="{{ link_target }}" rel="noopener"
class="{% if bookmark.unread %}text-italic{% endif %}">
{% if bookmark.favicon_file and request.user.profile.enable_favicons %}
{% if bookmark.favicon_file and request.user_profile.enable_favicons %}
<img src="{% static bookmark.favicon_file %}" alt="">
{% endif %}
{{ bookmark.resolved_title }}
</a>
</div>
{% if request.user.profile.display_url %}
{% if request.user_profile.display_url %}
<div class="url-path truncate">
<a href="{{ bookmark.url }}" target="{{ link_target }}" rel="noopener"
class="url-display text-sm">
@@ -46,7 +46,7 @@
</div>
{% endif %}
<div class="actions text-gray text-sm">
{% if request.user.profile.bookmark_date_display == 'relative' %}
{% if request.user_profile.bookmark_date_display == 'relative' %}
<span>
{% if bookmark.web_archive_snapshot_url %}
<a href="{{ bookmark.web_archive_snapshot_url }}"
@@ -61,7 +61,7 @@
</span>
<span class="separator">|</span>
{% endif %}
{% if request.user.profile.bookmark_date_display == 'absolute' %}
{% if request.user_profile.bookmark_date_display == 'absolute' %}
<span>
{% if bookmark.web_archive_snapshot_url %}
<a href="{{ bookmark.web_archive_snapshot_url }}"
@@ -103,7 +103,7 @@
<a href="?{% replace_query_param user=bookmark.owner.username %}">{{ bookmark.owner.username }}</a>
</span>
{% endif %}
{% if bookmark.notes and not request.user.profile.permanent_notes %}
{% if bookmark.notes and not request.user_profile.permanent_notes %}
<span class="separator">|</span>
<button class="btn btn-link btn-sm toggle-notes" title="Toggle notes">
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-notes" width="16" height="16"

View File

@@ -90,7 +90,7 @@
Unread bookmarks can be filtered for, and marked as read after you had a chance to look at them.
</div>
</div>
{% if request.user.profile.enable_sharing %}
{% if request.user_profile.enable_sharing %}
<div class="form-group">
<label for="{{ form.shared.id_for_label }}" class="form-checkbox">
{{ form.shared }}
@@ -98,7 +98,11 @@
<span>Share</span>
</label>
<div class="form-input-hint">
Share this bookmark with other users.
{% if request.user_profile.enable_public_sharing %}
Share this bookmark with other registered users and anonymous users.
{% else %}
Share this bookmark with other registered users.
{% endif %}
</div>
</div>
{% endif %}

View File

@@ -17,9 +17,9 @@
<title>linkding</title>
{# Include SASS styles, files are resolved from bookmarks/styles #}
{# Include specific theme variant based on user profile setting #}
{% if request.user.profile.theme == 'light' %}
{% if request.user_profile.theme == 'light' %}
<link href="{% sass_src 'theme-light.scss' %}" rel="stylesheet" type="text/css"/>
{% elif request.user.profile.theme == 'dark' %}
{% elif request.user_profile.theme == 'dark' %}
<link href="{% sass_src 'theme-dark.scss' %}" rel="stylesheet" type="text/css"/>
{% else %}
{# Use auto theme as fallback #}
@@ -51,11 +51,16 @@
<h1>linkding</h1>
</a>
</section>
{# Only show nav items menu when logged in #}
{% if request.user.is_authenticated %}
{# Only show nav items menu when logged in #}
<section class="navbar-section">
{% include 'bookmarks/nav_menu.html' %}
</section>
{% elif has_public_shares %}
{# Otherwise show link to shared bookmarks if there are publicly shared bookmarks #}
<section class="navbar-section">
<a href="{% url 'bookmarks:shared' %}" class="btn btn-link">Shared bookmarks</a>
</section>
{% endif %}
</div>
</header>

View File

@@ -20,7 +20,7 @@
<li>
<a href="{% url 'bookmarks:archived' %}" class="btn btn-link">Archived</a>
</li>
{% if request.user.profile.enable_sharing %}
{% if request.user_profile.enable_sharing %}
<li>
<a href="{% url 'bookmarks:shared' %}" class="btn btn-link">Shared</a>
</li>
@@ -59,7 +59,7 @@
<li style="padding-left: 1rem">
<a href="{% url 'bookmarks:archived' %}" class="btn btn-link">Archived</a>
</li>
{% if request.user.profile.enable_sharing %}
{% if request.user_profile.enable_sharing %}
<li style="padding-left: 1rem">
<a href="{% url 'bookmarks:shared' %}" class="btn btn-link">Shared</a>
</li>

View File

@@ -61,7 +61,8 @@
<div class="form-input-hint">
In strict mode, tags must be prefixed with a hash character (#).
In lax mode, tags can also be searched without the hash character.
Note that tags without the hash character are indistinguishable from search terms, which means the search result will also include bookmarks where a search term matches otherwise.
Note that tags without the hash character are indistinguishable from search terms, which means the search
result will also include bookmarks where a search term matches otherwise.
</div>
</div>
<div class="form-group">
@@ -77,7 +78,7 @@
documentation</a> on how to configure a custom favicon provider.
Icons are downloaded in the background, and it may take a while for them to show up.
</div>
{% if request.user.profile.enable_favicons and enable_refresh_favicons %}
{% if request.user_profile.enable_favicons and enable_refresh_favicons %}
<button class="btn mt-2" name="refresh_favicons">Refresh Favicons</button>
{% endif %}
{% if refresh_favicons_success_message %}
@@ -112,6 +113,17 @@
Disabling this feature will hide all previously shared bookmarks from other users.
</div>
</div>
<div class="form-group">
<label for="{{ form.enable_public_sharing.id_for_label }}" class="form-checkbox">
{{ form.enable_public_sharing }}
<i class="form-icon"></i> Enable public bookmark sharing
</label>
<div class="form-input-hint">
Makes shared bookmarks publicly accessible, without requiring a login.
That means that anyone with a link to this instance can view shared bookmarks via the <a
href="{% url 'bookmarks:shared' %}">shared bookmarks page</a>.
</div>
</div>
<div class="form-group">
<input type="submit" name="update_profile" value="Save" class="btn btn-primary mt-2">
{% if update_profile_success_message %}
@@ -196,4 +208,22 @@
</section>
</div>
<script>
// Automatically disable public bookmark sharing if bookmark sharing is disabled
const enableSharing = document.getElementById("{{ form.enable_sharing.id_for_label }}");
const enablePublicSharing = document.getElementById("{{ form.enable_public_sharing.id_for_label }}");
function updatePublicSharing() {
if (enableSharing.checked) {
enablePublicSharing.disabled = false;
} else {
enablePublicSharing.disabled = true;
enablePublicSharing.checked = false;
}
}
updatePublicSharing();
enableSharing.addEventListener("change", updatePublicSharing);
</script>
{% endblock %}