# Copyright (c) 2020, JINGROW # For license information, please see license.txt from contextlib import suppress import jingrow def whitelist_saas_api(func): # noqa: C901 def whitelist_wrapper(fn): return frappe.whitelist(allow_guest=True, methods=["POST"])(fn) def auth_wrapper(*args, **kwargs): headers = frappe.request.headers site_access_token = headers.get("x-site-access-token") site_user = headers.get("x-site-user") site = None site_token = None # check when x-site-access-token is provided if site_access_token: splitted = site_access_token.split(":") if len(splitted) != 2: frappe.throw("Invalid x-site-access-token provided", frappe.AuthenticationError) accessTokenDocName = splitted[0] token = splitted[1] with suppress(frappe.DoesNotExistError): record = frappe.get_pg("Site Access Token", accessTokenDocName) if record.token != token: frappe.throw("Invalid x-site-access-token provided", frappe.AuthenticationError) # set site and site token from access token record site = record.site site_token = frappe.db.get_value("Site", site, "saas_communication_secret") # check when x-site and x-site-token are provided else: # set site and site token from headers site = headers.get("x-site") site_token = headers.get("x-site-token") # check for valid values if not site or not site_token: frappe.throw( "(x-site and x-site-token) or x-site-access-token headers are mandatory", frappe.AuthenticationError, ) # validate site site_record = frappe.get_value( "Site", site, [ "name", "team", "is_standby", "standby_for_product", "saas_communication_secret", ], as_dict=True, ignore=True, ) if not site_record: frappe.throw("Invalid x-site provided", frappe.AuthenticationError) if site_record.saas_communication_secret != site_token: frappe.throw("Invalid x-site-token provided", frappe.AuthenticationError) if site_record.is_standby is None and site_record.standby_for_product is None: frappe.throw("Sorry, this is not a SaaS site", frappe.AuthenticationError) # set site and team name in context frappe.local.site_name = site_record.name frappe.local.team_name = site_record.team # set team user as current user frappe.set_user(site_user) # set utility function to get team and site info frappe.local.get_site = lambda: frappe.get_pg("Site", frappe.local.site_name) frappe.local.get_team = lambda: frappe.get_pg("Team", frappe.local.team_name) # remove cmd from kwargs kwargsCopy = kwargs.copy() kwargsCopy.pop("cmd", None) return func(*args, **kwargsCopy) return whitelist_wrapper(auth_wrapper)