Browse Source

Allow logged-out users to browse the site

This is messy in a few ways and needs some reworking, but should be fine
for testing and initial enabling public visibility. An invite is still
required for registration, and the registration page isn't even
currently linked anywhere since people should usually get a registration
link as the invite.

May roll this back and/or do follow-up commits if it makes the site
break.
merge-requests/55/head
Deimos 6 years ago
parent
commit
610bcefd25
  1. 12
      tildes/scss/modules/_site-footer.scss
  2. 13
      tildes/scss/themes/_theme_base.scss
  3. 27
      tildes/tildes/auth.py
  4. 20
      tildes/tildes/templates/base.jinja2
  5. 36
      tildes/tildes/templates/error_403.jinja2
  6. 28
      tildes/tildes/templates/home.jinja2
  7. 11
      tildes/tildes/templates/macros/comments.jinja2
  8. 6
      tildes/tildes/templates/macros/user.jinja2
  9. 2
      tildes/tildes/templates/notifications_unread.jinja2
  10. 2
      tildes/tildes/templates/topic.jinja2
  11. 2
      tildes/tildes/templates/topic_listing.jinja2
  12. 2
      tildes/tildes/templates/user.jinja2
  13. 21
      tildes/tildes/views/topic.py
  14. 2
      tildes/tildes/views/user.py

12
tildes/scss/modules/_site-footer.scss

@ -37,3 +37,15 @@
margin-left: 1rem;
}
}
.site-footer-theme-selection {
font-style: normal;
margin-bottom: 1rem;
select {
width: auto;
font-size: 0.6rem;
height: 1.4rem;
padding: 0 0 0 0.2rem;
}
}

13
tildes/scss/themes/_theme_base.scss

@ -61,12 +61,6 @@
}
}
a.logged-in-user-username:visited,
a.site-header-context:visited,
a.site-header-logo:visited {
color: unset;
}
@include syntax-highlighting($is-light);
blockquote {
@ -299,7 +293,7 @@
@include theme-special-label(map-get($theme, "topic-tag-spoiler"), $is-light);
}
.logged-in-user-username {
.logged-in-user-username, .logged-in-user-username:visited {
color: map-get($theme, "foreground-primary");
}
@ -346,12 +340,11 @@
background-color: map-get($theme, "background-primary");
}
.site-header-context,
.site-header-username {
.site-header-context, .site-header-context:visited {
color: map-get($theme, "foreground-primary");
}
.site-header-logo {
.site-header-logo, .site-header-logo:visited {
color: map-get($theme, "foreground-highlight");
}

27
tildes/tildes/auth.py

@ -10,7 +10,7 @@ from pyramid.authorization import ACLAuthorizationPolicy
from pyramid.config import Configurator
from pyramid.httpexceptions import HTTPFound
from pyramid.request import Request
from pyramid.security import ACLDenied, ACLPermitsResult, Allow, Authenticated, Everyone
from pyramid.security import Allow, Everyone
from tildes.models.user import User
@ -72,11 +72,7 @@ def includeme(config: Configurator) -> None:
# default permission
config.set_root_factory(DefaultRootFactory)
# Set the authorization policy to a custom one that always returns a "denied" result
# if the user isn't logged in. When overall site access is no longer being
# restricted, the AuthorizedOnlyPolicy class can just be replaced with the standard
# ACLAuthorizationPolicy
config.set_authorization_policy(AuthorizedOnlyPolicy())
config.set_authorization_policy(ACLAuthorizationPolicy())
config.set_authentication_policy(
SessionAuthenticationPolicy(callback=auth_callback)
@ -92,25 +88,6 @@ def includeme(config: Configurator) -> None:
config.add_request_method(has_any_permission, "has_any_permission")
class AuthorizedOnlyPolicy(ACLAuthorizationPolicy):
"""ACLAuthorizationPolicy override that always denies logged-out users."""
def permits(
self, context: Any, principals: Sequence[Any], permission: str
) -> ACLPermitsResult:
"""Deny logged-out users, otherwise pass up to normal policy."""
if Authenticated not in principals:
return ACLDenied(
"<authorized only>",
"<no ACLs checked yet>",
permission,
principals,
context,
)
return super().permits(context, principals, permission)
def has_any_permission(
request: Request, permissions: Sequence[str], context: Any
) -> bool:

20
tildes/tildes/templates/base.jinja2

@ -90,6 +90,26 @@
</aside>
<footer id="site-footer" data-js-hide-sidebar-if-open>
{# Show the theme-selection dropdown if the user isn't logged in #}
{% if not request.user %}
<div class="site-footer-theme-selection">
<label for="theme">Theme:</label>
<select class="form-select" name="theme" id="theme" data-js-theme-selector>
{% for (theme, description) in (
("white", "White"),
("light", "Solarized Light"),
("dark", "Solarized Dark"),
("black", "Black")) %}
<option value="{{ theme }}"
{{ 'selected' if theme == request.cookies.get("theme", "white") else '' }}
>
{{ description }}
</option>
{% endfor %}
</select>
</div>
{% endif %}
<p>Tildes is a non-profit site that respects its users and prioritizes quality content.</p>
<p>It has no advertising, no investors, and is supported by <a href="https://docs.tildes.net/donate">your donations</a>.</p>
<ul class="site-footer-links">

36
tildes/tildes/templates/error_403.jinja2

@ -3,36 +3,12 @@
{% extends 'base_no_sidebar.jinja2' %}
{% block title %}
{% if not request.user %}
Invite-only alpha
{% else %}
Error 403 (Forbidden)
{% endif %}
{% endblock %}
{% block main_heading %}
{% if request.user %}
Error 403 (Forbidden)
{% endif %}
{% endblock %}
{% block title %}Error 403 (Forbidden){% endblock %}
{% block content %}
{% if not request.user %}
<div class="empty">
<h2 class="empty-title">Tildes is currently in invite-only alpha</h2>
<p class="empty-subtitle">To learn more about Tildes, <a href="https://blog.tildes.net/announcing-tildes">read the announcement post</a>.</p>
<p class="empty-subtitle">There are also some pages available on <a href="https://docs.tildes.net">the docs site</a>.</p>
<div class="empty-action">
<a href="/login" class="btn btn-primary">Log in</a>
<a href="/register" class="btn btn-primary">Register</a>
</div>
</div>
{% else %}
<p>You don't have access to this page.</p>
{% endif %}
<div class="empty">
<h2 class="empty-title">Error 403 (Forbidden)</h2>
<p class="empty-subtitle">You don't have access to this page.</p>
<div class="empty-action"><a href="/" class="btn btn-primary">Back to the home page</a></div>
</div>
{% endblock %}

28
tildes/tildes/templates/home.jinja2

@ -10,7 +10,8 @@
{% block header_context_link %}{% endblock %}
{% block content %}
{% if request.user and request.user.subscriptions %}
{% if request.user %}
{% if request.user.subscriptions %}
{{ super() }}
{% else %}
<div class="empty">
@ -19,27 +20,41 @@
<div class="empty-action"><a href="/groups" class="btn btn-primary">Browse the list of groups</a></div>
</div>
{% endif %}
{% else %}
{{ super() }}
{% endif %}
{% endblock %}
{% block sidebar %}
{{ search_form() }}
<h2>Home</h2>
<p>The home page shows topics from groups that you're subscribed to.</p>
{% if request.user %}
{% if request.user.subscriptions %}
<p>The home page shows topics from groups that you're subscribed to.</p>
{% else %}
<p>The home page shows topics from all the groups on Tildes.</p>
<p>Logged-in users can choose which groups they subscribe to and/or filter out posts with particular tags.</p>
{% endif %}
{% if groups %}
<ul class="nav">
{% if request.user %}
<li>Subscriptions</li>
{% else %}
<li>Groups</li>
{% endif %}
<ul class="nav">
{% for subscription in request.user.subscriptions|sort(attribute='group') %}
<li class="nav-item"><a href="/~{{ subscription.group.path }}">~{{ subscription.group.path }}</a></li>
{% for group in groups|sort %}
<li class="nav-item"><a href="/~{{ group.path }}">~{{ group.path }}</a></li>
{% endfor %}
</ul>
</ul>
<a href="/groups" class="btn btn-primary">Browse the list of groups</a>
{% endif %}
{% if not (tag or unfiltered) %}
{% if request.user and not (tag or unfiltered) %}
<hr>
<details>
<summary>Filtered topic tags ({{ request.user.filtered_topic_tags|length }})</summary>
@ -53,5 +68,4 @@
<a class="btn btn-link" href="/settings/filters">Edit filtered tags</a>
</details>
{% endif %}
{% endif %}
{% endblock %}

11
tildes/tildes/templates/macros/comments.jinja2

@ -150,6 +150,17 @@
{{ comment.rendered_html|safe }}
</div>
{# Show votes at the bottom only if the viewer is logged out #}
{% if not request.user and comment.num_votes > 0 %}
<div class="comment-votes">{{ comment.num_votes }}
{% trans num_votes=comment.num_votes %}
vote
{% pluralize %}
votes
{% endtrans %}
</div>
{% endif %}
<menu class="post-buttons">
{% if request.has_permission('vote', comment) %}
{% if comment.user_voted is defined and comment.user_voted %}

6
tildes/tildes/templates/macros/user.jinja2

@ -2,8 +2,8 @@
{# SPDX-License-Identifier: AGPL-3.0-or-later #}
{% macro logged_in_user_info() %}
{% if request.user %}
<div class="logged-in-user-info">
{% if request.user %}
<a class="logged-in-user-username" href="/user/{{ request.user }}">{{ request.user }}</a>
{% if request.user.num_unread_messages > 0 %}
@ -25,6 +25,8 @@
{% endtrans %}
</a>
{% endif %}
</div>
{% else %}
<a class="text-small" href="/login">Log in</a>
{% endif %}
</div>
{% endmacro %}

2
tildes/tildes/templates/notifications_unread.jinja2

@ -73,5 +73,5 @@
<p><a href="/notifications">Go to previously read notifications</a></p>
{% endif %}
{{ comment_label_options_template(comment_label_options) }}
{% if request.user %}{{ comment_label_options_template(comment_label_options) }}{% endif %}
{% endblock %}

2
tildes/tildes/templates/topic.jinja2

@ -265,7 +265,7 @@
</article>
{{ comment_label_options_template(comment_label_options) }}
{% if request.user %}{{ comment_label_options_template(comment_label_options) }}{% endif %}
{% endblock content %}
{% block sidebar %}

2
tildes/tildes/templates/topic_listing.jinja2

@ -74,7 +74,7 @@
</div>
</form>
{% if is_default_view is defined and not is_default_view %}
{% if request.user and is_default_view is defined and not is_default_view %}
<form
{% if is_single_group %}
data-ic-patch-to="{{ request.route_url(

2
tildes/tildes/templates/user.jinja2

@ -85,7 +85,7 @@
{% endif %}
{% endif %}
{{ comment_label_options_template(comment_label_options) }}
{% if request.user %}{{ comment_label_options_template(comment_label_options) }}{% endif %}
{% endblock %}

21
tildes/tildes/views/topic.py

@ -86,7 +86,7 @@ def post_group_topics(
raise HTTPFound(location=new_topic.permalink)
@view_config(route_name="home", renderer="home.jinja2")
@view_config(route_name="home", renderer="home.jinja2") # noqa
@view_config(route_name="group", renderer="topic_listing.jinja2")
@use_kwargs(TopicListingSchema())
def get_group_topics(
@ -104,7 +104,13 @@ def get_group_topics(
# pylint: disable=too-many-arguments
if request.matched_route.name == "home":
# on the home page, include topics from the user's subscribed groups
# (or all groups, if logged-out)
if request.user:
groups = [sub.group for sub in request.user.subscriptions]
else:
groups = [
group for group in request.query(Group).all() if group.path != "test"
]
else:
# otherwise, just topics from the single group that we're looking at
groups = [request.context]
@ -141,7 +147,7 @@ def get_group_topics(
query = query.after_id36(after)
# apply topic tag filters unless they're disabled or viewing a single tag
if not (tag or unfiltered):
if request.user and not (tag or unfiltered):
# pylint: disable=protected-access
query = query.filter(
~Topic._tags.descendant_of( # type: ignore
@ -160,6 +166,7 @@ def get_group_topics(
return {
"group": request.context,
"groups": groups,
"topics": topics,
"order": order,
"order_options": TopicSortOption,
@ -323,9 +330,11 @@ def post_comment_on_topic(request: Request, markdown: str) -> HTTPFound:
raise HTTPFound(location=topic.permalink)
def _get_default_settings(request: Request, order: Any) -> DefaultSettings:
def _get_default_settings(request: Request, order: Any) -> DefaultSettings: # noqa
if isinstance(request.context, Group):
is_home_page = False
if request.user:
user_settings = (
request.query(UserGroupSettings)
.filter(
@ -334,13 +343,15 @@ def _get_default_settings(request: Request, order: Any) -> DefaultSettings:
)
.one_or_none()
)
else:
user_settings = None
else:
is_home_page = True
user_settings = None
if user_settings and user_settings.default_order:
default_order = user_settings.default_order
elif request.user.home_default_order:
elif request.user and request.user.home_default_order:
default_order = request.user.home_default_order
else:
default_order = TopicSortOption.ACTIVITY
@ -353,7 +364,7 @@ def _get_default_settings(request: Request, order: Any) -> DefaultSettings:
if user_settings and user_settings.default_period:
user_default = user_settings.default_period
default_period = ShortTimePeriod().deserialize(user_default)
elif request.user.home_default_period:
elif request.user and request.user.home_default_period:
user_default = request.user.home_default_period
default_period = ShortTimePeriod().deserialize(user_default)
else:

2
tildes/tildes/views/user.py

@ -69,7 +69,7 @@ def get_user(
query = query.join_all_relationships()
# include removed posts if the user's looking at their own page or is an admin
if user == request.user or request.user.is_admin:
if request.user and (user == request.user or request.user.is_admin):
query = query.include_removed()
result_sets.append(query.get_page(per_page))

Loading…
Cancel
Save