Merge pull request #243 from mouse-reeve/post-privacy

post privacy
This commit is contained in:
Mouse Reeve 2020-10-28 13:17:28 -07:00 committed by GitHub
commit bdde69473a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 164 additions and 127 deletions

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 23 KiB

View file

@ -1,10 +1,10 @@
@font-face {
font-family: 'icomoon';
src: url('fonts/icomoon.eot?v0wquk');
src: url('fonts/icomoon.eot?v0wquk#iefix') format('embedded-opentype'),
url('fonts/icomoon.ttf?v0wquk') format('truetype'),
url('fonts/icomoon.woff?v0wquk') format('woff'),
url('fonts/icomoon.svg?v0wquk#icomoon') format('svg');
src: url('fonts/icomoon.eot?7ifunb');
src: url('fonts/icomoon.eot?7ifunb#iefix') format('embedded-opentype'),
url('fonts/icomoon.ttf?7ifunb') format('truetype'),
url('fonts/icomoon.woff?7ifunb') format('woff'),
url('fonts/icomoon.svg?7ifunb#icomoon') format('svg');
font-weight: normal;
font-style: normal;
font-display: block;
@ -13,7 +13,7 @@
[class^="icon-"], [class*=" icon-"] {
/* use !important to prevent issues with browser extensions that change fonts */
font-family: 'icomoon' !important;
speak: none;
speak: never;
font-style: normal;
font-weight: normal;
font-variant: normal;
@ -25,26 +25,71 @@
-moz-osx-font-smoothing: grayscale;
}
.icon-arrow-right:before {
.icon-envelope:before {
content: "\e900";
}
.icon-arrow-left:before {
content: "\e910";
.icon-arrow-right:before {
content: "\e901";
}
.icon-arrow-up:before {
content: "\e911";
}
.icon-arrow-down:before {
content: "\e912";
.icon-bell:before {
content: "\e902";
}
.icon-x:before {
content: "\e902";
content: "\e903";
}
.icon-cancel:before {
content: "\e902";
.icon-quote-close:before {
content: "\e904";
}
.icon-close:before {
content: "\e902";
.icon-quote-open:before {
content: "\e905";
}
.icon-image:before {
content: "\e906";
}
.icon-pencil:before {
content: "\e907";
}
.icon-list:before {
content: "\e908";
}
.icon-unlock:before {
content: "\e909";
}
.icon-globe:before {
content: "\e90a";
}
.icon-lock:before {
content: "\e90b";
}
.icon-chain-broken:before {
content: "\e90c";
}
.icon-chain:before {
content: "\e90d";
}
.icon-comments:before {
content: "\e90e";
}
.icon-comment:before {
content: "\e90f";
}
.icon-boost:before {
content: "\e910";
}
.icon-arrow-left:before {
content: "\e911";
}
.icon-arrow-up:before {
content: "\e912";
}
.icon-arrow-down:before {
content: "\e913";
}
.icon-home:before {
content: "\e914";
}
.icon-local:before {
content: "\e915";
}
.icon-search:before {
content: "\e986";
@ -61,78 +106,3 @@
.icon-heart:before {
content: "\e9da";
}
.icon-local:before {
content: "\e914";
}
.icon-home:before {
content: "\e913";
}
.icon-quote-close:before {
content: "\e903";
}
.icon-quote-open:before {
content: "\e904";
}
.icon-image:before {
content: "\e905";
}
.icon-photo:before {
content: "\e905";
}
.icon-picture-o:before {
content: "\e905";
}
.icon-pencil:before {
content: "\e906";
}
.icon-list:before {
content: "\e907";
}
.icon-unlock:before {
content: "\e908";
}
.icon-unlisted:before {
content: "\e908";
}
.icon-globe:before {
content: "\e909";
}
.icon-global:before {
content: "\e909";
}
.icon-federated:before {
content: "\e909";
}
.icon-public:before {
content: "\e909";
}
.icon-lock:before {
content: "\e90a";
}
.icon-private:before {
content: "\e90a";
}
.icon-chain-broken:before {
content: "\e90b";
}
.icon-unlink:before {
content: "\e90b";
}
.icon-chain:before {
content: "\e90c";
}
.icon-link:before {
content: "\e90c";
}
.icon-comments:before {
content: "\e90d";
}
.icon-comment:before {
content: "\e90e";
}
.icon-boost:before {
content: "\e90f";
}
.icon-bell:before {
content: "\e901";
}

View file

@ -23,7 +23,6 @@
{% csrf_token %}
<input type="hidden" name="book" value="{{ book.id }}">
<input type="hidden" name="user" value="{{ request.user.id }}">
<input type="hidden" name="privacy" value="public">
<div class="control">
<label class="label" for="id_name_{{ book.id }}_review">Title:</label>
<input type="text" name="name" maxlength="255" class="input" required="" id="id_name_{{ book.id }}_review" placeholder="My review of '{{ book.title }}'">
@ -44,7 +43,17 @@
<textarea name="content" class="textarea" id="id_content_{{ book.id }}_review"></textarea>
</div>
<div class="control is-grouped">
<div class="select">
<select name="privacy">
<option value="public" selected>Public</option>
<option value="unlisted">Unlisted</option>
<option value="followers">Followers only</option>
<option value="direct">Private</option>
</select>
</div>
<button class="button is-primary" type="submit">post review</button>
</div>
</form>
</div>
@ -60,7 +69,17 @@
<label class="label" for="id_content_{{ book.id }}_comment">Comment:</label>
<textarea name="content" class="textarea" id="id_content_{{ book.id }}_comment" placeholder="Some thoughts on '{{ book.title }}'"></textarea>
</div>
<div class="control is-grouped">
<div class="select">
<select name="privacy">
<option value="public" selected>Public</option>
<option value="unlisted">Unlisted</option>
<option value="followers">Followers only</option>
<option value="direct">Private</option>
</select>
</div>
<button class="button is-primary" type="submit">post comment</button>
</div>
</form>
</div>
@ -80,7 +99,17 @@
<label class="label" for="id_content_{{ book.id }}_quote">Comment:</label>
<textarea name="content" class="textarea is-small" id="id_content_{{ book.id }}_quote"></textarea>
</div>
<div class="control is-grouped">
<div class="select">
<select name="privacy">
<option value="public" selected>Public</option>
<option value="unlisted">Unlisted</option>
<option value="followers">Followers only</option>
<option value="direct">Private</option>
</select>
</div>
<button class="button is-primary" type="submit">post quote</button>
</div>
</form>
</div>
</div>

View file

@ -6,7 +6,7 @@
{% csrf_token %}
<input type="hidden" name="reply_parent" value="{{ activity.id }}">
<input type="hidden" name="user" value="{{ request.user.id }}">
<input type="hidden" name="privacy" value="public">
<input type="hidden" name="privacy" value="{{ activity.privacy }}">
<textarea name="content" placeholder="Leave a comment..." id="id_content_{{ activity.id }}" required="true"></textarea>
<button class="button" type="submit">
<span class="icon icon-comment">

View file

@ -23,15 +23,29 @@
{% endif %}
<div class="card-footer-item">
<span class="icon icon-public">
{% if status.privacy == 'public' %}
<span class="icon icon-globe">
<span class="is-sr-only">Public post</span>
</span>
{% elif status.privacy == 'unlisted' %}
<span class="icon icon-unlock">
<span class="is-sr-only">Unlisted post</span>
</span>
{% elif status.privacy == 'followers' %}
<span class="icon icon-lock">
<span class="is-sr-only">Followers-only post</span>
</span>
{% else %}
<span class="icon icon-envelope">
<span class="is-sr-only">Private post</span>
</span>
{% endif %}
{% if status.user == request.user %}
<form name="delete-{{status.id}}" action="/delete-status" method="post">
{% csrf_token %}
<input type="hidden" name="status" value="{{ status.id }}">
<button type="submit">
<span class="icon icon-cancel">
<span class="icon icon-x">
<span class="is-sr-only">Delete post</span>
</span>
</button>

View file

@ -130,17 +130,22 @@ def get_activity_feed(user, filter_level, model=models.Status):
if filter_level in ['friends', 'home']:
# people you follow and direct mentions
activities = activities.filter(
Q(user__in=following, privacy='public') | \
Q(mention_users=user)
Q(user__in=following, privacy__in=['public', 'unlisted', 'followers']) | \
Q(mention_users=user) | Q(user=user)
)
elif filter_level == 'self':
activities = activities.filter(user=user, privacy='public')
elif filter_level == 'local':
# everyone on this instance
activities = activities.filter(user__local=True, privacy='public')
# everyone on this instance except unlisted
activities = activities.filter(
Q(user__in=following, privacy='followers') | Q(privacy='public'),
user__local=True
)
else:
# all activities from everyone you federate with
activities = activities.filter(privacy='public')
activities = activities.filter(
Q(user__in=following, privacy='followers') | Q(privacy='public')
)
return activities
@ -386,9 +391,14 @@ def status_page(request, username, status_id):
except ValueError:
return HttpResponseNotFound()
# the url should have the poster's username in it
if user != status.user:
return HttpResponseNotFound()
# make sure the user is authorized to see the status
if not status_visible_to_user(request.user, status):
return HttpResponseNotFound()
if is_api_request(request):
return JsonResponse(status.to_activity(), encoder=ActivityEncoder)
@ -397,6 +407,19 @@ def status_page(request, username, status_id):
}
return TemplateResponse(request, 'status.html', data)
def status_visible_to_user(viewer, status):
''' is a user authorized to view a status? '''
if viewer == status.user or status.privacy in ['public', 'unlisted']:
return True
if status.privacy == 'followers' and \
status.user.followers.filter(id=viewer.id).first():
return True
if status.privacy == 'direct' and \
status.mention_users.filter(id=viewer.id).first():
return True
return False
@csrf_exempt
def replies_page(request, username, status_id):