2015-11-01 17:10:52 +01:00
|
|
|
from __future__ import absolute_import
|
2016-05-25 15:02:02 +02:00
|
|
|
|
|
|
|
from django.utils.translation import ugettext as _
|
2016-06-05 04:10:13 +02:00
|
|
|
from django.http import HttpResponse, HttpRequest
|
2013-11-04 17:22:58 +01:00
|
|
|
from django.views.decorators.csrf import csrf_exempt
|
2013-11-07 19:57:13 +01:00
|
|
|
from django.contrib.auth.views import login as django_login_page
|
|
|
|
from django.http import HttpResponseRedirect
|
2013-10-17 22:55:09 +02:00
|
|
|
|
2016-06-05 04:10:13 +02:00
|
|
|
from zilencer.models import Deployment
|
|
|
|
|
2014-02-14 16:50:42 +01:00
|
|
|
from zerver.decorator import has_request_variables, REQ
|
2013-10-24 00:27:52 +02:00
|
|
|
from zerver.lib.actions import internal_send_message
|
2014-02-05 00:35:32 +01:00
|
|
|
from zerver.lib.redis_utils import get_redis_client
|
2016-06-24 02:26:09 +02:00
|
|
|
from zerver.lib.response import json_success, json_error, json_response
|
2014-02-14 16:50:42 +01:00
|
|
|
from zerver.lib.validator import check_dict
|
2017-01-04 05:30:48 +01:00
|
|
|
from zerver.models import get_realm, get_user_profile_by_email, \
|
2016-11-18 01:51:13 +01:00
|
|
|
get_realm_by_email_domain, UserProfile, Realm
|
2015-11-01 17:10:52 +01:00
|
|
|
from .error_notify import notify_server_error, notify_browser_error
|
2016-06-24 02:26:09 +02:00
|
|
|
|
2014-01-17 15:36:39 +01:00
|
|
|
import time
|
2013-10-17 22:55:09 +02:00
|
|
|
|
2016-12-08 05:06:51 +01:00
|
|
|
from typing import Dict, Optional, Any, Text
|
2016-06-05 04:10:13 +02:00
|
|
|
|
2014-02-05 00:35:32 +01:00
|
|
|
client = get_redis_client()
|
2014-01-17 17:40:26 +01:00
|
|
|
|
|
|
|
def has_enough_time_expired_since_last_message(sender_email, min_delay):
|
2016-12-08 05:06:51 +01:00
|
|
|
# type: (Text, float) -> bool
|
2014-01-17 17:40:26 +01:00
|
|
|
# This function returns a boolean, but it also has the side effect
|
|
|
|
# of noting that a new message was received.
|
|
|
|
key = 'zilencer:feedback:%s' % (sender_email,)
|
|
|
|
t = int(time.time())
|
|
|
|
last_time = client.getset(key, t)
|
|
|
|
if last_time is None:
|
|
|
|
return True
|
|
|
|
delay = t - int(last_time)
|
|
|
|
return delay > min_delay
|
2013-10-17 22:55:09 +02:00
|
|
|
|
|
|
|
def get_ticket_number():
|
2016-06-05 04:10:13 +02:00
|
|
|
# type: () -> int
|
2017-01-08 16:27:32 +01:00
|
|
|
num_file = '/var/tmp/.feedback-bot-ticket-number'
|
2013-10-17 22:55:09 +02:00
|
|
|
try:
|
2017-01-08 16:27:32 +01:00
|
|
|
ticket_number = int(open(num_file).read()) + 1
|
|
|
|
except Exception:
|
2013-10-17 22:55:09 +02:00
|
|
|
ticket_number = 1
|
2017-01-08 16:27:32 +01:00
|
|
|
open(num_file, 'w').write('%d' % (ticket_number,))
|
2013-10-17 22:55:09 +02:00
|
|
|
return ticket_number
|
|
|
|
|
|
|
|
@has_request_variables
|
2014-02-14 16:50:42 +01:00
|
|
|
def submit_feedback(request, deployment, message=REQ(validator=check_dict([]))):
|
2016-12-08 05:06:51 +01:00
|
|
|
# type: (HttpRequest, Deployment, Dict[str, Text]) -> HttpResponse
|
2013-10-17 22:55:09 +02:00
|
|
|
domainish = message["sender_domain"]
|
2017-01-04 05:30:48 +01:00
|
|
|
if get_realm("zulip") not in deployment.realms.all():
|
2016-07-30 00:33:29 +02:00
|
|
|
domainish += u" via " + deployment.name
|
2013-12-24 06:16:29 +01:00
|
|
|
subject = "%s" % (message["sender_email"],)
|
2013-10-17 22:55:09 +02:00
|
|
|
|
|
|
|
if len(subject) > 60:
|
|
|
|
subject = subject[:57].rstrip() + "..."
|
|
|
|
|
2016-07-30 00:33:29 +02:00
|
|
|
content = u''
|
2014-01-17 15:36:39 +01:00
|
|
|
sender_email = message['sender_email']
|
2013-10-17 22:55:09 +02:00
|
|
|
|
2014-01-17 15:36:39 +01:00
|
|
|
# We generate ticket numbers if it's been more than a few minutes
|
|
|
|
# since their last message. This avoids some noise when people use
|
|
|
|
# enter-send.
|
2014-01-17 17:40:26 +01:00
|
|
|
need_ticket = has_enough_time_expired_since_last_message(sender_email, 180)
|
|
|
|
|
|
|
|
if need_ticket:
|
2014-01-17 15:36:39 +01:00
|
|
|
ticket_number = get_ticket_number()
|
|
|
|
content += '\n~~~'
|
|
|
|
content += '\nticket Z%03d (@support please ack)' % (ticket_number,)
|
|
|
|
content += '\nsender: %s' % (message['sender_full_name'],)
|
|
|
|
content += '\nemail: %s' % (sender_email,)
|
|
|
|
if 'sender_domain' in message:
|
|
|
|
content += '\nrealm: %s' % (message['sender_domain'],)
|
|
|
|
content += '\n~~~'
|
|
|
|
content += '\n\n'
|
2013-10-17 22:55:09 +02:00
|
|
|
|
|
|
|
content += message['content']
|
|
|
|
|
2017-01-22 05:23:36 +01:00
|
|
|
internal_send_message(realm_for_email("feedback@zulip.com"), "feedback@zulip.com",
|
|
|
|
"stream", "support", subject, content)
|
2013-10-17 22:55:09 +02:00
|
|
|
|
|
|
|
return HttpResponse(message['sender_email'])
|
2013-10-24 00:27:52 +02:00
|
|
|
|
2013-11-13 19:12:22 +01:00
|
|
|
@has_request_variables
|
2016-05-31 16:29:39 +02:00
|
|
|
def report_error(request, deployment, type=REQ(), report=REQ(validator=check_dict([]))):
|
2016-12-08 05:06:51 +01:00
|
|
|
# type: (HttpRequest, Deployment, Text, Dict[str, Any]) -> HttpResponse
|
2016-08-11 21:44:09 +02:00
|
|
|
return do_report_error(deployment.name, type, report)
|
|
|
|
|
|
|
|
def do_report_error(deployment_name, type, report):
|
2016-12-08 05:06:51 +01:00
|
|
|
# type: (Text, Text, Dict[str, Any]) -> HttpResponse
|
2016-08-11 21:44:09 +02:00
|
|
|
report['deployment'] = deployment_name
|
2013-11-13 19:12:22 +01:00
|
|
|
if type == 'browser':
|
|
|
|
notify_browser_error(report)
|
|
|
|
elif type == 'server':
|
|
|
|
notify_server_error(report)
|
|
|
|
else:
|
2016-05-25 15:02:02 +02:00
|
|
|
return json_error(_("Invalid type parameter"))
|
2016-01-27 01:59:30 +01:00
|
|
|
return json_success()
|
2013-11-07 19:57:13 +01:00
|
|
|
|
|
|
|
def realm_for_email(email):
|
2016-06-05 04:10:13 +02:00
|
|
|
# type: (str) -> Optional[Realm]
|
2013-11-07 19:57:13 +01:00
|
|
|
try:
|
|
|
|
user = get_user_profile_by_email(email)
|
|
|
|
return user.realm
|
|
|
|
except UserProfile.DoesNotExist:
|
|
|
|
pass
|
|
|
|
|
2016-11-09 02:40:54 +01:00
|
|
|
return get_realm_by_email_domain(email)
|
2013-11-07 19:57:13 +01:00
|
|
|
|
2013-10-24 00:27:52 +02:00
|
|
|
# Requests made to this endpoint are UNAUTHENTICATED
|
|
|
|
@csrf_exempt
|
|
|
|
@has_request_variables
|
|
|
|
def lookup_endpoints_for_user(request, email=REQ()):
|
2016-06-05 04:10:13 +02:00
|
|
|
# type: (HttpRequest, str) -> HttpResponse
|
2013-10-24 00:27:52 +02:00
|
|
|
try:
|
2013-11-07 19:57:13 +01:00
|
|
|
return json_response(realm_for_email(email).deployment.endpoints)
|
|
|
|
except AttributeError:
|
2016-05-25 15:02:02 +02:00
|
|
|
return json_error(_("Cannot determine endpoint for user."), status=404)
|
2013-11-07 19:57:13 +01:00
|
|
|
|
|
|
|
def account_deployment_dispatch(request, **kwargs):
|
2016-06-05 04:10:13 +02:00
|
|
|
# type: (HttpRequest, **Any) -> HttpResponse
|
2013-11-07 19:57:13 +01:00
|
|
|
sso_unknown_email = False
|
|
|
|
if request.method == 'POST':
|
|
|
|
email = request.POST['username']
|
|
|
|
realm = realm_for_email(email)
|
2013-10-24 00:27:52 +02:00
|
|
|
try:
|
2013-11-07 19:57:13 +01:00
|
|
|
return HttpResponseRedirect(realm.deployment.base_site_url)
|
2013-10-24 00:27:52 +02:00
|
|
|
except AttributeError:
|
2013-11-07 19:57:13 +01:00
|
|
|
# No deployment found for this user/email
|
|
|
|
sso_unknown_email = True
|
2013-11-05 19:30:18 +01:00
|
|
|
|
2013-11-07 19:57:13 +01:00
|
|
|
template_response = django_login_page(request, **kwargs)
|
2013-11-14 16:26:36 +01:00
|
|
|
template_response.context_data['desktop_sso_dispatch'] = True
|
|
|
|
template_response.context_data['desktop_sso_unknown_email'] = sso_unknown_email
|
2013-11-07 19:57:13 +01:00
|
|
|
return template_response
|