def suppressed_emails(request): params = dict(params_from_request(request).copy()) try: mac_verify(params) except Exception as exc: raise BadRequestError(str(exc)) try: decrypted_str = decrypt(params['token']) decrypted_json = json.loads(decrypted_str) except Exception as exc: log.exception(repr(exc)) raise BadRequestError() if decrypted_json.get('key') != Portal.get_singleton().external_api_key: raise NotFoundError() action = decrypted_json.get('action') if not action: raise RequiredParameterMissingError('action') if action == 'delete': Notification.objects(suppressed=True).delete() elif action == 'unsuppress': Notification.objects.update(suppressed=False) else: raise BadRequestError('Action "%s" not supported' % action) return Response("OK", 200)
def confirm_unsubscription(request): """ Tags: notifications --- Creates a new notification override. Accepts an override creation request and adds the corresponding override, creating a new override policy if it does not exist. --- """ params = params_from_request(request) try: decrypted_str = decrypt(params["token"]) decrypted_json = json.loads(decrypted_str) except Exception as exc: log.exception(repr(exc)) raise BadRequestError(ERROR_MSG) option = params.get("option") if not option: raise RequiredParameterMissingError("option") try: mac_verify(decrypted_json) except Exception as exc: raise BadRequestError(exc) try: org_id = decrypted_json["org_id"] except KeyError as err: log.exception(repr(err)) raise BadRequestError(ERROR_MSG) try: org = Organization.objects.get(id=org_id) except Organization.DoesNotExist: raise OrganizationNotFound() rid = decrypted_json.get("rid", "") rtype = decrypted_json.get("rtype", "") email = decrypted_json.get("email") user_id = decrypted_json.get("user_id") channel = decrypted_json.get("channel") if not (email or user_id) and channel in CHANNELS: log.critical("Got invalid/insufficient data: %s", decrypted_json) raise BadRequestError(ERROR_MSG) qr = me.Q(owner=org) qr &= me.Q(user_id=user_id) if user_id else me.Q(email=email) np = UserNotificationPolicy.objects(qr).first() if not np: np = UserNotificationPolicy(owner=org, user_id=user_id, email=email) for override in np.overrides: if override.blocks(channel, rtype, rid): return json.dumps({"response": "channel_blocked"}) override = NotificationOverride() if option == 'channel': override.channel = channel elif option == 'rule': override.rid = rid override.rtype = rtype override.channel = channel elif option == 'all': pass else: raise BadRequestError("Invalid option '%s'" % option) np.overrides.append(override) try: np.save() except me.ValidationError as err: log.critical("Failed to save %s: %r", np, err) raise BadRequestError(ERROR_MSG) return json.dumps({"response": "override_added"})
def request_unsubscription(request): """ Tags: notifications --- Returns an unsubscription request page. Accepts a request, validates the unsubscribe token and returns a rendered template, with a link and another token to confirm unsubscribing. --- """ params = params_from_request(request) # Decrypt URL params. try: decrypted_str = decrypt(params["token"]) decrypted_json = json.loads(decrypted_str) except Exception as exc: log.exception(repr(exc)) raise BadRequestError(ERROR_MSG) # Verify HMAC. try: mac_verify(decrypted_json) except Exception as exc: raise BadRequestError(exc) try: org_id = decrypted_json["org_id"] except KeyError as err: log.exception(repr(err)) raise BadRequestError(ERROR_MSG) # Get Organization. try: org = Organization.objects.get(id=org_id) except Organization.DoesNotExist: raise OrganizationNotFound() # Verify required parameters are present. rid = decrypted_json.get("rid", "") rtype = decrypted_json.get("rtype", "") email = decrypted_json.get("email") user_id = decrypted_json.get("user_id") channel = decrypted_json.get("channel") if not (email or user_id) and channel in CHANNELS: log.critical("Got invalid/insufficient data: %s", decrypted_json) raise BadRequestError(ERROR_MSG) inputs = { "uri": config.CORE_URI, "csrf_token": get_csrf_token(request), "rid": rid, "rype": rtype, "channel": channel, "org": org.id } unsubscribe_options = [{"id": "all", "title": "all mist.io emails"}] if channel == "EmailReports": unsubscribe_options.insert(0, { "id": "channel", "title": "mist.io weekly reports" }) else: # channel == "EmailAlert": unsubscribe_options.insert(0, { "id": "channel", "title": "all mist.io email alerts" }) if rtype == 'rule': unsubscribe_options.insert(0, { "id": "rule", "title": "alerts about this rule" }) inputs.update({'options': unsubscribe_options}) # Get the user's notification policy. qr = me.Q(owner=org) qr &= me.Q(user_id=user_id) if user_id else me.Q(email=email) np = UserNotificationPolicy.objects(qr).first() # Check if an override already exists. if np: for override in np.overrides: if override.blocks(channel, rtype, rid): return render_to_response('templates/is_unsubscribed.pt', inputs) # Render template to unsubscribe. try: hmac_params = decrypted_json.copy() mac_sign(hmac_params) encrypted = encrypt(json.dumps(hmac_params)) inputs.update({ "token": encrypted, # TODO Make the template customizable/dynamic based on the action. "action": decrypted_json["action"], "csrf_token": get_csrf_token(request), }) except Exception as exc: log.exception(repr(exc)) raise BadRequestError(ERROR_MSG) return render_to_response('templates/unsubscribe.pt', inputs)