Browse Source

Merge branch 'send-new-message' into 'develop'

Add a "send new message" link in the PM section - Issue 91

See merge request tildes/tildes!141
merge-requests/141/merge
Joe H 2 days ago
parent
commit
144b0dcddf
  1. 1
      tildes/tildes/models/user/user.py
  2. 11
      tildes/tildes/routes.py
  3. 6
      tildes/tildes/schemas/message.py
  4. 5
      tildes/tildes/templates/macros/user_menu.jinja2
  5. 41
      tildes/tildes/templates/new_message_from_inbox.jinja2
  6. 2
      tildes/tildes/views/api/web/exceptions.py
  7. 54
      tildes/tildes/views/api/web/user.py
  8. 1
      tildes/tildes/views/exceptions.py

1
tildes/tildes/models/user/user.py

@ -226,6 +226,7 @@ class User(DatabaseModel):
"generate_invite",
"search_posts",
"view_removed_posts",
"send_message",
):
acl.append((Allow, self.user_id, permission))

11
tildes/tildes/routes.py

@ -85,6 +85,8 @@ def includeme(config: Configurator) -> None:
"/conversations/{conversation_id36}",
factory=message_conversation_by_id36,
)
# Send new PM to user
config.add_route("new_message_from_inbox", "/new", factory=LoggedInFactory)
config.add_route("settings", "/settings", factory=LoggedInFactory)
with config.route_prefix_context("/settings"):
@ -196,7 +198,14 @@ class LoggedInFactory:
specific resource (such as a topic or message).
"""
__acl__ = ((Allow, Authenticated, "view"),)
__acl__ = [
(Allow, Authenticated, "view"),
(
Allow,
Authenticated,
"message",
), # Add this line to give the 'message' permission to authenticated users
]
def __init__(self, request: Request):
"""Initialize - no-op, but needs to take the request as an arg."""

6
tildes/tildes/schemas/message.py

@ -29,3 +29,9 @@ class MessageReplySchema(Schema):
markdown = Markdown()
rendered_html = String(dump_only=True)
created_time = DateTime(dump_only=True)
class NewMessageConversationSchema(MessageConversationSchema):
"""Marshmallow schema for starting a new message conversation."""
recipient = String(required=True)

5
tildes/tildes/templates/macros/user_menu.jinja2

@ -65,6 +65,11 @@
Sent messages
</a>
</li>
<li class="nav-item {{ 'active' if route == 'new_message_from_inbox' else '' }}">
<a href="/messages/new">
New message
</a>
</li>
</ul>
<li>Misc</li>

41
tildes/tildes/templates/new_message_from_inbox.jinja2

@ -0,0 +1,41 @@
{# Copyright (c) 2018 Tildes contributors <code@tildes.net> #}
{# SPDX-License-Identifier: AGPL-3.0-or-later #}
{% extends 'base_no_sidebar.jinja2' %}
{% from 'macros/forms.jinja2' import markdown_textarea %}
{% block title %}New private message conversation{% endblock %}
{% block main_heading %}
Send a new private message
{% endblock %}
{% block content %}
<form
method="post"
autocomplete="off"
action="/messages/new"
data-ic-post-to="/messages/new"
data-js-prevent-double-submit
data-js-confirm-leave-page-unsaved
>
<input type="hidden" name="csrf_token" value="{{ get_csrf_token() }}">
<div class="form-group">
<label class="form-label" for="recipient">Recipient</label>
<input class="form-input" id="recipient" name="recipient" type="text" placeholder="Recipient's username" required>
</div>
<div class="form-group">
<label class="form-label" for="subject">Subject</label>
<input class="form-input" id="subject" name="subject" type="text" placeholder="Subject" value="{{ subject }}" required>
</div>
{{ markdown_textarea(text=message) }}
<div class="form-buttons">
<button type="submit" class="btn btn-primary">Send message</button>
</div>
</form>
{% endblock %}

2
tildes/tildes/views/api/web/exceptions.py

@ -75,6 +75,8 @@ def error_to_text_response(request: Request) -> Response:
elif isinstance(request.exception, HTTPBadRequest):
if response.title == "Bad CSRF Token":
response.text = "Page expired, reload and try again"
elif "Recipient user not found" in str(response):
response.text = "Username not found"
else:
response.text = "Unknown error"

54
tildes/tildes/views/api/web/user.py

@ -13,6 +13,9 @@ from pyramid.httpexceptions import (
HTTPForbidden,
HTTPUnauthorized,
HTTPUnprocessableEntity,
HTTPNotFound,
HTTPFound,
HTTPBadRequest
)
from pyramid.request import Request
from pyramid.response import Response
@ -28,6 +31,13 @@ from tildes.schemas.topic import TopicSchema
from tildes.schemas.user import UserSchema
from tildes.views import IC_NOOP
from tildes.views.decorators import ic_view_config, use_kwargs
from tildes.models.message import MessageConversation, MessageReply
from tildes.schemas.message import NewMessageConversationSchema
from pyramid.view import view_config
#from pyramid.security import authenticated_userid
PASSWORD_FIELD = UserSchema(only=("password",)).fields["password"]
@ -423,3 +433,47 @@ def delete_user_ban(request: Request) -> Response:
request.context.is_banned = False
return Response("Unbanned")
@view_config(
route_name="new_message_from_inbox",
renderer="new_message_from_inbox.jinja2",
request_method="GET",
permission="view",
)
def get_new_message_form(request: Request) -> dict:
"""Render form for entering a new private message to send."""
return {}
# This is the view function for handling the form submission
@view_config(
route_name="new_message_from_inbox", request_method="POST", permission="message"
)
@use_kwargs(
NewMessageConversationSchema(only=("subject", "markdown", "recipient")),
location="form",
)
def post_new_message(
request: Request, subject: str, markdown: str, recipient: str
) -> HTTPFound:
"""Start a new message conversation with a user."""
recipient_user = (
request.db_session.query(User).filter_by(username=recipient).one_or_none()
)
if recipient_user is None:
raise HTTPBadRequest("Recipient user not found")
new_conversation = MessageConversation(
sender=request.user,
recipient=recipient_user,
subject=subject,
markdown=markdown,
)
request.db_session.add(new_conversation)
raise HTTPFound(request.route_url("messages_sent"))

1
tildes/tildes/views/exceptions.py

@ -104,3 +104,4 @@ def logged_out_forbidden(request: Request) -> HTTPFound:
login_url = request.route_url("login", _query={"from_url": forbidden_path})
return HTTPFound(location=login_url)
Loading…
Cancel
Save