diff --git a/zerver/decorator.py b/zerver/decorator.py index 21384b750d..d16fb59eb0 100644 --- a/zerver/decorator.py +++ b/zerver/decorator.py @@ -125,8 +125,9 @@ def get_client_name(request, is_json_view): else: return "Unspecified" -def process_client(request, user_profile, is_json_view=False): - client_name = get_client_name(request, is_json_view) +def process_client(request, user_profile, is_json_view=False, client_name=None): + if client_name is None: + client_name = get_client_name(request, is_json_view) # Transitional hack for early 2014. Eventually the ios clients # will all report ZulipiOS, and we can remove the next couple lines. @@ -164,28 +165,31 @@ def validate_api_key(role, api_key): return profile # Use this for webhook views that don't get an email passed in. -def api_key_only_webhook_view(view_func): - @csrf_exempt - @has_request_variables - @wraps(view_func) - def _wrapped_view_func(request, api_key=REQ, - *args, **kwargs): +def api_key_only_webhook_view(client_name): + def _wrapped_view_func(view_func): + @csrf_exempt + @has_request_variables + @wraps(view_func) + def _wrapped_func_arguments(request, api_key=REQ, + *args, **kwargs): - try: - user_profile = UserProfile.objects.get(api_key=api_key) - except UserProfile.DoesNotExist: - raise JsonableError("Invalid API key") - if not user_profile.is_active: - raise JsonableError("Account not active") - if user_profile.realm.deactivated: - raise JsonableError("Realm for account has been deactivated") + try: + user_profile = UserProfile.objects.get(api_key=api_key) + except UserProfile.DoesNotExist: + raise JsonableError("Invalid API key") + if not user_profile.is_active: + raise JsonableError("Account not active") + if user_profile.realm.deactivated: + raise JsonableError("Realm for account has been deactivated") - request.user = user_profile - request._email = user_profile.email - process_client(request, user_profile) - if settings.RATE_LIMITING: - rate_limit_user(request, user_profile, domain='all') - return view_func(request, user_profile, *args, **kwargs) + request.user = user_profile + request._email = user_profile.email + webhook_client_name = "Zulip{}Webhook".format(client_name) + process_client(request, user_profile, client_name=webhook_client_name) + if settings.RATE_LIMITING: + rate_limit_user(request, user_profile, domain='all') + return view_func(request, user_profile, request.client, *args, **kwargs) + return _wrapped_func_arguments return _wrapped_view_func # From Django 1.8, modified to leave off ?next=/ diff --git a/zerver/views/webhooks/circleci.py b/zerver/views/webhooks/circleci.py index b0e3ddedb3..cf93a819cb 100644 --- a/zerver/views/webhooks/circleci.py +++ b/zerver/views/webhooks/circleci.py @@ -13,14 +13,14 @@ CIRCLECI_MESSAGE_TEMPLATE = '[Build]({build_url}) triggered by {username} on {br FAILED_STATUS = 'failed' -@api_key_only_webhook_view +@api_key_only_webhook_view('CircleCI') @has_request_variables -def api_circleci_webhook(request, user_profile, payload=REQ(argument_type='body'), stream=REQ(default='circleci')): +def api_circleci_webhook(request, user_profile, client, payload=REQ(argument_type='body'), stream=REQ(default='circleci')): payload = payload['payload'] subject = get_subject(payload) body = get_body(payload) - check_send_message(user_profile, get_client('ZulipCircleCIWebhook'), 'stream', [stream], subject, body) + check_send_message(user_profile, client, 'stream', [stream], subject, body) return json_success() def get_subject(payload): diff --git a/zerver/views/webhooks/codeship.py b/zerver/views/webhooks/codeship.py index 9935396406..aa54cf0da8 100644 --- a/zerver/views/webhooks/codeship.py +++ b/zerver/views/webhooks/codeship.py @@ -19,9 +19,9 @@ CODESHIP_STATUS_MAPPER = { } -@api_key_only_webhook_view +@api_key_only_webhook_view('Codeship') @has_request_variables -def api_codeship_webhook(request, user_profile, payload=REQ(argument_type='body'), +def api_codeship_webhook(request, user_profile, client, payload=REQ(argument_type='body'), stream=REQ(default='codeship')): try: payload = payload['build'] @@ -30,7 +30,7 @@ def api_codeship_webhook(request, user_profile, payload=REQ(argument_type='body' except KeyError as e: return json_error("Missing key {} in JSON".format(e.message)) - check_send_message(user_profile, get_client('ZulipCodeshipWebhook'), 'stream', [stream], subject, body) + check_send_message(user_profile, client, 'stream', [stream], subject, body) return json_success() diff --git a/zerver/views/webhooks/jira.py b/zerver/views/webhooks/jira.py index a94b2be43e..176c30a518 100644 --- a/zerver/views/webhooks/jira.py +++ b/zerver/views/webhooks/jira.py @@ -79,9 +79,10 @@ def convert_jira_markup(content, realm): return content -@api_key_only_webhook_view +@api_key_only_webhook_view("JIRA") @has_request_variables -def api_jira_webhook(request, user_profile, payload=REQ(argument_type='body'), +def api_jira_webhook(request, user_profile, client, + payload=REQ(argument_type='body'), stream=REQ(default='jira')): def get_in(payload, keys, default=''): try: @@ -168,6 +169,6 @@ def api_jira_webhook(request, user_profile, payload=REQ(argument_type='body'), logging.warning("Got JIRA event type we don't understand: %s" % (event,)) return json_error("Unknown JIRA event type") - check_send_message(user_profile, get_client("ZulipJIRAWebhook"), "stream", + check_send_message(user_profile, client, "stream", [stream], subject, content) return json_success() diff --git a/zerver/views/webhooks/newrelic.py b/zerver/views/webhooks/newrelic.py index acc5309c2b..46a959f7e4 100644 --- a/zerver/views/webhooks/newrelic.py +++ b/zerver/views/webhooks/newrelic.py @@ -7,9 +7,9 @@ from zerver.lib.validator import check_dict from zerver.decorator import REQ, has_request_variables, api_key_only_webhook_view -@api_key_only_webhook_view +@api_key_only_webhook_view("NewRelic") @has_request_variables -def api_newrelic_webhook(request, user_profile, stream=REQ(), +def api_newrelic_webhook(request, user_profile, client, stream=REQ(), alert=REQ(validator=check_dict([]), default=None), deployment=REQ(validator=check_dict([]), default=None)): if alert: @@ -27,6 +27,6 @@ def api_newrelic_webhook(request, user_profile, stream=REQ(), else: return json_error("Unknown webhook request") - check_send_message(user_profile, get_client("ZulipNewRelicWebhook"), "stream", + check_send_message(user_profile, client, "stream", [stream], subject, content) return json_success() diff --git a/zerver/views/webhooks/pagerduty.py b/zerver/views/webhooks/pagerduty.py index 2f6c3bad0e..fe65a86fd7 100644 --- a/zerver/views/webhooks/pagerduty.py +++ b/zerver/views/webhooks/pagerduty.py @@ -65,18 +65,18 @@ def build_pagerduty_formatdict(message): return format_dict -def send_raw_pagerduty_json(user_profile, stream, message, topic): +def send_raw_pagerduty_json(user_profile, client, stream, message, topic): subject = topic or 'pagerduty' body = ( u'Unknown pagerduty message\n' u'``` py\n' u'%s\n' u'```') % (pprint.pformat(message),) - check_send_message(user_profile, get_client('ZulipPagerDutyWebhook'), 'stream', + check_send_message(user_profile, client, 'stream', [stream], subject, body) -def send_formated_pagerduty(user_profile, stream, message_type, format_dict, topic): +def send_formated_pagerduty(user_profile, client, stream, message_type, format_dict, topic): if message_type in ('incident.trigger', 'incident.unacknowledge'): template = (u':imp: Incident ' u'[{incident_num}]({incident_url}) {action} by ' @@ -97,25 +97,25 @@ def send_formated_pagerduty(user_profile, stream, message_type, format_dict, top subject = topic or u'incident {incident_num}'.format(**format_dict) body = template.format(**format_dict) - check_send_message(user_profile, get_client('ZulipPagerDutyWebhook'), 'stream', + check_send_message(user_profile, client, 'stream', [stream], subject, body) -@api_key_only_webhook_view +@api_key_only_webhook_view('PagerDuty') @has_request_variables -def api_pagerduty_webhook(request, user_profile, payload=REQ(argument_type='body'), +def api_pagerduty_webhook(request, user_profile, client, payload=REQ(argument_type='body'), stream=REQ(default='pagerduty'), topic=REQ(default=None)): for message in payload['messages']: message_type = message['type'] if message_type not in PAGER_DUTY_EVENT_NAMES: - send_raw_pagerduty_json(user_profile, stream, message, topic) + send_raw_pagerduty_json(user_profile, client, stream, message, topic) try: format_dict = build_pagerduty_formatdict(message) except: - send_raw_pagerduty_json(user_profile, stream, message, topic) + send_raw_pagerduty_json(user_profile, client, stream, message, topic) else: - send_formated_pagerduty(user_profile, stream, message_type, format_dict, topic) + send_formated_pagerduty(user_profile, client, stream, message_type, format_dict, topic) return json_success() diff --git a/zerver/views/webhooks/pingdom.py b/zerver/views/webhooks/pingdom.py index e2c53b01bc..fd4e22c85c 100644 --- a/zerver/views/webhooks/pingdom.py +++ b/zerver/views/webhooks/pingdom.py @@ -27,9 +27,9 @@ SUPPORTED_CHECK_TYPES = ( ) -@api_key_only_webhook_view +@api_key_only_webhook_view('Pingdom') @has_request_variables -def api_pingdom_webhook(request, user_profile, payload=REQ(argument_type='body'), stream=REQ(default='pingdom')): +def api_pingdom_webhook(request, user_profile, client, payload=REQ(argument_type='body'), stream=REQ(default='pingdom')): check_type = get_check_type(payload) if check_type in SUPPORTED_CHECK_TYPES: @@ -38,7 +38,7 @@ def api_pingdom_webhook(request, user_profile, payload=REQ(argument_type='body') else: return json_error('Unsupported check_type: {check_type}'.format(check_type=check_type)) - check_send_message(user_profile, get_client('ZulipPingdomWebhook'), 'stream', [stream], subject, body) + check_send_message(user_profile, client, 'stream', [stream], subject, body) return json_success() diff --git a/zerver/views/webhooks/pivotal.py b/zerver/views/webhooks/pivotal.py index e4450a1fdb..725ae90eff 100644 --- a/zerver/views/webhooks/pivotal.py +++ b/zerver/views/webhooks/pivotal.py @@ -147,9 +147,9 @@ def api_pivotal_webhook_v5(request, user_profile, stream): return subject, content -@api_key_only_webhook_view +@api_key_only_webhook_view("Pivotal") @has_request_variables -def api_pivotal_webhook(request, user_profile, stream=REQ()): +def api_pivotal_webhook(request, user_profile, client, stream=REQ()): subject = content = None try: subject, content = api_pivotal_webhook_v3(request, user_profile, stream) @@ -165,6 +165,6 @@ def api_pivotal_webhook(request, user_profile, stream=REQ()): if subject is None or content is None: return json_error("Unable to handle Pivotal payload") - check_send_message(user_profile, get_client("ZulipPivotalWebhook"), "stream", + check_send_message(user_profile, client, "stream", [stream], subject, content) return json_success() diff --git a/zerver/views/webhooks/taiga.py b/zerver/views/webhooks/taiga.py index 43b336b9fb..325c785b3e 100644 --- a/zerver/views/webhooks/taiga.py +++ b/zerver/views/webhooks/taiga.py @@ -28,9 +28,9 @@ import ujson from six.moves import range -@api_key_only_webhook_view +@api_key_only_webhook_view('Taiga') @has_request_variables -def api_taiga_webhook(request, user_profile, message=REQ(argument_type='body'), +def api_taiga_webhook(request, user_profile, client, message=REQ(argument_type='body'), stream=REQ(default='taiga'), topic=REQ(default='General')): parsed_events = parse_message(message) @@ -38,7 +38,7 @@ def api_taiga_webhook(request, user_profile, message=REQ(argument_type='body'), for event in parsed_events: content += generate_content(event) + '\n' - check_send_message(user_profile, get_client('ZulipTaigaWebhook'), 'stream', [stream], topic, content) + check_send_message(user_profile, client, 'stream', [stream], topic, content) return json_success() diff --git a/zerver/views/webhooks/teamcity.py b/zerver/views/webhooks/teamcity.py index aa99b19aca..009f3b1de3 100644 --- a/zerver/views/webhooks/teamcity.py +++ b/zerver/views/webhooks/teamcity.py @@ -31,9 +31,9 @@ def get_teamcity_property_value(property_list, name): return property['value'] return None -@api_key_only_webhook_view +@api_key_only_webhook_view('Teamcity') @has_request_variables -def api_teamcity_webhook(request, user_profile, payload=REQ(argument_type='body'), +def api_teamcity_webhook(request, user_profile, client, payload=REQ(argument_type='body'), stream=REQ(default='teamcity')): message = payload['build'] @@ -85,8 +85,8 @@ def api_teamcity_webhook(request, user_profile, payload=REQ(argument_type='body' return json_success() body = "Your personal build of " + body - check_send_message(user_profile, get_client('ZulipTeamcityWebhook'), 'private', [teamcity_user.email], topic, body) + check_send_message(user_profile, client, 'private', [teamcity_user.email], topic, body) return json_success() - check_send_message(user_profile, get_client('ZulipTeamcityWebhook'), 'stream', [stream], topic, body) + check_send_message(user_profile, client, 'stream', [stream], topic, body) return json_success() diff --git a/zerver/views/webhooks/travis.py b/zerver/views/webhooks/travis.py index 5f624b3ff2..c5a9a4a4d4 100644 --- a/zerver/views/webhooks/travis.py +++ b/zerver/views/webhooks/travis.py @@ -8,9 +8,10 @@ from zerver.lib.validator import check_dict, check_string import ujson -@api_key_only_webhook_view +@api_key_only_webhook_view('Travis') @has_request_variables -def api_travis_webhook(request, user_profile, stream=REQ(default='travis'), +def api_travis_webhook(request, user_profile, client, + stream=REQ(default='travis'), topic=REQ(default=None), message=REQ('payload', validator=check_dict([ ['author_name', check_string], @@ -40,5 +41,5 @@ def api_travis_webhook(request, user_profile, stream=REQ(default='travis'), body = template % (author, message_type, emoji, changes, build_url) - check_send_message(user_profile, get_client('ZulipTravisWebhook'), 'stream', [stream], topic, body) + check_send_message(user_profile, client, 'stream', [stream], topic, body) return json_success() diff --git a/zerver/views/webhooks/yo.py b/zerver/views/webhooks/yo.py index 243998d78a..9d34bc49cc 100644 --- a/zerver/views/webhooks/yo.py +++ b/zerver/views/webhooks/yo.py @@ -7,12 +7,12 @@ from zerver.decorator import REQ, has_request_variables, api_key_only_webhook_vi import ujson -@api_key_only_webhook_view +@api_key_only_webhook_view('Yo') @has_request_variables -def api_yo_app_webhook(request, user_profile, email=REQ(default=None), +def api_yo_app_webhook(request, user_profile, client, email=REQ(default=None), username=REQ(default='Yo Bot'), topic=REQ(default='None'), user_ip=REQ(default='None')): body = ('Yo from %s') % (username,) - check_send_message(user_profile, get_client('ZulipYoWebhook'), 'private', [email], topic, body) + check_send_message(user_profile, client, 'private', [email], topic, body) return json_success()