def url_script(request): """ Returns to a mist authenticated user, a self-auth/signed url for fetching a script's file. READ permission required on script. --- script_id: in: path required: true type: string """ auth_context = auth_context_from_request(request) script_id = request.matchdict['script_id'] try: Script.objects.get(owner=auth_context.owner, id=script_id, deleted=None) except Script.DoesNotExist: raise NotFoundError('Script does not exist.') # SEC require READ permission on script auth_context.check_perm('script', 'read', script_id) # build HMAC and inject into the `curl` command hmac_params = {'action': 'fetch_script', 'object_id': script_id} expires_in = 60 * 15 mac_sign(hmac_params, expires_in) url = "%s/api/v1/fetch" % config.CORE_URI encode_params = urllib.urlencode(hmac_params) r_url = url + '?' + encode_params return r_url
def get_unsub_link(self, user_id, email=None): params = self.unsub_params params.update({'user_id': user_id, 'email': email}) token = {'token': encrypt(json.dumps(params))} mac_sign(token) return '%s/unsubscribe?%s' % (config.CORE_URI, urllib.parse.urlencode(token))
def get_unsuppress_link(action): assert action in ( 'unsuppress', 'delete', ) params = { 'action': action, 'key': Portal.get_singleton().external_api_key } token = {'token': encrypt(json.dumps(params))} mac_sign(token) return '%s/suppressed-alerts?%s' % (config.CORE_URI, urllib.parse.urlencode(token))
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)