def validate_oauth(): from dataent.oauth import get_url_delimiter form_dict = dataent.local.form_dict authorization_header = dataent.get_request_header("Authorization").split( " ") if dataent.get_request_header("Authorization") else None if authorization_header and authorization_header[0].lower() == "bearer": from dataent.integrations.oauth2 import get_oauth_server token = authorization_header[1] r = dataent.request parsed_url = urlparse(r.url) access_token = {"access_token": token} uri = parsed_url.scheme + "://" + parsed_url.netloc + parsed_url.path + "?" + urlencode( access_token) http_method = r.method body = r.get_data() headers = r.headers required_scopes = dataent.db.get_value( "OAuth Bearer Token", token, "scopes").split(get_url_delimiter()) valid, oauthlib_request = get_oauth_server().verify_request( uri, http_method, body, headers, required_scopes) if valid: dataent.set_user( dataent.db.get_value("OAuth Bearer Token", token, "user")) dataent.local.form_dict = form_dict
def get_url(uri=None, full_address=False): """get app url from request""" host_name = dataent.local.conf.host_name or dataent.local.conf.hostname if uri and (uri.startswith("http://") or uri.startswith("https://")): return uri if not host_name: if hasattr(dataent.local, "request" ) and dataent.local.request and dataent.local.request.host: protocol = 'https://' if 'https' == dataent.get_request_header( 'X-Forwarded-Proto', "") else 'http://' host_name = protocol + dataent.local.request.host elif dataent.local.site: protocol = 'http://' if dataent.local.conf.ssl_certificate: protocol = 'https://' elif dataent.local.conf.wildcard: domain = dataent.local.conf.wildcard.get('domain') if domain and dataent.local.site.endswith( domain) and dataent.local.conf.wildcard.get( 'ssl_certificate'): protocol = 'https://' host_name = protocol + dataent.local.site else: host_name = dataent.db.get_value("Website Settings", "Website Settings", "subdomain") if not host_name: host_name = "http://localhost" if host_name and not (host_name.startswith("http://") or host_name.startswith("https://")): host_name = "http://" + host_name if not uri and full_address: uri = dataent.get_request_header("REQUEST_URI", "") port = dataent.conf.http_port or dataent.conf.webserver_port if not (dataent.conf.restart_supervisor_on_update or dataent.conf.restart_systemd_on_update ) and host_name and not url_contains_port(host_name) and port: host_name = host_name + ':' + str(port) url = urljoin(host_name, uri) if uri else host_name return url
def verify_request(): woocommerce_settings = dataent.get_doc("Woocommerce Settings") sig = base64.b64encode( hmac.new( woocommerce_settings.secret.encode('utf8'), dataent.request.data, hashlib.sha256 ).digest() ) if dataent.request.data and \ dataent.get_request_header("X-Wc-Webhook-Signature") and \ not sig == bytes(dataent.get_request_header("X-Wc-Webhook-Signature").encode()): dataent.throw(_("Unverified Webhook Data")) dataent.set_user(woocommerce_settings.creation_user)
def innerfn(fn): settings = dataent.get_doc(doctype) if dataent.request and settings and settings.get( secret_key) and not dataent.flags.in_test: sig = base64.b64encode( hmac.new( settings.get(secret_key).encode('utf8'), dataent.request.data, hashlib.sha256).digest()) if dataent.request.data and \ dataent.get_request_header(hmac_key) and \ not sig == bytes(dataent.get_request_header(hmac_key).encode()): dataent.throw(_("Unverified Webhook Data")) dataent.set_user(settings.modified_by) return fn
def validate_auth_via_api_keys(): """ authentication using api key and api secret set user """ try: authorization_header = dataent.get_request_header( "Authorization", None).split(" ") if dataent.get_request_header( "Authorization") else None if authorization_header and authorization_header[0] == 'Basic': token = dataent.safe_decode( base64.b64decode(authorization_header[1])).split(":") validate_api_key_secret(token[0], token[1]) elif authorization_header and authorization_header[0] == 'token': token = authorization_header[1].split(":") validate_api_key_secret(token[0], token[1]) except Exception as e: raise e
def __init__(self): # Get Environment variables self.domain = dataent.request.host if self.domain and self.domain.startswith('www.'): self.domain = self.domain[4:] if dataent.get_request_header('X-Forwarded-For'): dataent.local.request_ip = (dataent.get_request_header( 'X-Forwarded-For').split(",")[0]).strip() elif dataent.get_request_header('REMOTE_ADDR'): dataent.local.request_ip = dataent.get_request_header( 'REMOTE_ADDR') else: dataent.local.request_ip = '127.0.0.1' # language self.set_lang() # load cookies dataent.local.cookie_manager = CookieManager() # set db self.connect() # login dataent.local.login_manager = LoginManager() if dataent.form_dict._lang: lang = get_lang_code(dataent.form_dict._lang) if lang: dataent.local.lang = lang self.validate_csrf_token() # write out latest cookies dataent.local.cookie_manager.init_cookies() # check status check_session_stopped()
def authenticate_signature(r): """Returns True if the received signature matches the generated signature""" received_signature = dataent.get_request_header("Webhook-Signature") if not received_signature: return False for key in get_webhook_keys(): computed_signature = hmac.new(key.encode("utf-8"), r.get_data(), hashlib.sha256).hexdigest() if hmac.compare_digest(str(received_signature), computed_signature): return True return False
def validate_csrf_token(self): if dataent.local.request and dataent.local.request.method == "POST": if not dataent.local.session: return if not dataent.local.session.data.csrf_token \ or dataent.local.session.data.device=="mobile" \ or dataent.conf.get('ignore_csrf', None): # not via boot return csrf_token = dataent.get_request_header("X-Dataent-CSRF-Token") if not csrf_token and "csrf_token" in dataent.local.form_dict: csrf_token = dataent.local.form_dict.csrf_token del dataent.local.form_dict["csrf_token"] if dataent.local.session.data.csrf_token != csrf_token: dataent.local.flags.disable_traceback = True dataent.throw(_("Invalid Request"), dataent.CSRFTokenError)
def init_request(request): dataent.local.request = request dataent.local.is_ajax = dataent.get_request_header( "X-Requested-With") == "XMLHttpRequest" site = _site or request.headers.get( 'X-Dataent-Site-Name') or get_site_name(request.host) dataent.init(site=site, sites_path=_sites_path) if not (dataent.local.conf and dataent.local.conf.db_name): # site does not exist raise NotFound if dataent.local.conf.get('maintenance_mode'): raise dataent.SessionStopped make_form_dict(request) dataent.local.http_request = dataent.auth.HTTPRequest()
def authenticate_signature(post_url=None): """Returns True if the received signature matches the generated signature""" received_signature = dataent.get_request_header("X-Mandrill-Signature") # seems like a dummy post request if not received_signature: return False to_hash = get_post_url_for_hashing(post_url) for key in get_webhook_keys(): # generate signature using the webhook key hashed = hmac.new(key.encode("utf-8"), to_hash, hashlib.sha1) generated_signature = hashed.digest().encode("base64").rstrip('\n') # matched => authenticated if received_signature == generated_signature: return True # no match => failure return False
def authenticate_client(self, request, *args, **kwargs): cookie_dict = get_cookie_dict_from_headers(request) #Get ClientID in URL if request.client_id: oc = dataent.get_doc("OAuth Client", request.client_id) else: #Extract token, instantiate OAuth Bearer Token and use clientid from there. if "refresh_token" in dataent.form_dict: oc = dataent.get_doc( "OAuth Client", dataent.db.get_value( "OAuth Bearer Token", {"refresh_token": dataent.form_dict["refresh_token"]}, 'client')) elif "token" in dataent.form_dict: oc = dataent.get_doc( "OAuth Client", dataent.db.get_value("OAuth Bearer Token", dataent.form_dict["token"], 'client')) else: oc = dataent.get_doc( "OAuth Client", dataent.db.get_value( "OAuth Bearer Token", dataent.get_request_header("Authorization").split(" ") [1], 'client')) try: request.client = request.client or oc.as_dict() except Exception as e: print("Failed body authentication: Application %s does not exist". format(cid=request.client_id)) return dataent.session.user == unquote( cookie_dict.get('user_id', "Guest"))
def handle_exception(e): response = None http_status_code = getattr(e, "http_status_code", 500) return_as_message = False if dataent.get_request_header('Accept') and ( dataent.local.is_ajax or 'application/json' in dataent.get_request_header('Accept')): # handle ajax responses first # if the request is ajax, send back the trace or error message response = dataent.utils.response.report_error(http_status_code) elif (http_status_code == 500 and isinstance(e, pymysql.InternalError) and e.args[0] in (ER.LOCK_WAIT_TIMEOUT, ER.LOCK_DEADLOCK)): http_status_code = 508 elif http_status_code == 401: dataent.respond_as_web_page( _("Session Expired"), _("Your session has expired, please login again to continue."), http_status_code=http_status_code, indicator_color='red') return_as_message = True elif http_status_code == 403: dataent.respond_as_web_page( _("Not Permitted"), _("You do not have enough permissions to complete the action"), http_status_code=http_status_code, indicator_color='red') return_as_message = True elif http_status_code == 404: dataent.respond_as_web_page( _("Not Found"), _("The resource you are looking for is not available"), http_status_code=http_status_code, indicator_color='red') return_as_message = True else: traceback = "<pre>" + dataent.get_traceback() + "</pre>" if dataent.local.flags.disable_traceback: traceback = "" dataent.respond_as_web_page("Server Error", traceback, http_status_code=http_status_code, indicator_color='red', width=640) return_as_message = True if e.__class__ == dataent.AuthenticationError: if hasattr(dataent.local, "login_manager"): dataent.local.login_manager.clear_cookies() if http_status_code >= 500: dataent.logger().error('Request Error', exc_info=True) make_error_snapshot(e) if return_as_message: response = dataent.website.render.render( "message", http_status_code=http_status_code) return response
def _order(*args, **kwargs): woocommerce_settings = dataent.get_doc("Woocommerce Settings") if dataent.flags.woocomm_test_order_data: fd = dataent.flags.woocomm_test_order_data event = "created" elif dataent.request and dataent.request.data: verify_request() fd = json.loads(dataent.request.data) event = dataent.get_request_header("X-Wc-Webhook-Event") else: return "success" if event == "created": raw_billing_data = fd.get("billing") customer_woo_com_email = raw_billing_data.get("email") if dataent.get_value("Customer",{"woocommerce_email": customer_woo_com_email}): # Edit link_customer_and_address(raw_billing_data,1) else: # Create link_customer_and_address(raw_billing_data,0) items_list = fd.get("line_items") for item in items_list: item_woo_com_id = item.get("product_id") if dataent.get_value("Item",{"woocommerce_id": item_woo_com_id}): #Edit link_item(item,1) else: link_item(item,0) customer_name = raw_billing_data.get("first_name") + " " + raw_billing_data.get("last_name") new_sales_order = dataent.new_doc("Sales Order") new_sales_order.customer = customer_name created_date = fd.get("date_created").split("T") new_sales_order.transaction_date = created_date[0] new_sales_order.po_no = fd.get("id") new_sales_order.woocommerce_id = fd.get("id") new_sales_order.naming_series = woocommerce_settings.sales_order_series or "SO-WOO-" placed_order_date = created_date[0] raw_date = datetime.datetime.strptime(placed_order_date, "%Y-%m-%d") raw_delivery_date = dataent.utils.add_to_date(raw_date,days = 7) order_delivery_date_str = raw_delivery_date.strftime('%Y-%m-%d') order_delivery_date = str(order_delivery_date_str) new_sales_order.delivery_date = order_delivery_date default_set_company = dataent.get_doc("Global Defaults") company = raw_billing_data.get("company") or default_set_company.default_company found_company = dataent.get_doc("Company",{"name":company}) company_abbr = found_company.abbr new_sales_order.company = company for item in items_list: woocomm_item_id = item.get("product_id") found_item = dataent.get_doc("Item",{"woocommerce_id": woocomm_item_id}) ordered_items_tax = item.get("total_tax") new_sales_order.append("items",{ "item_code": found_item.item_code, "item_name": found_item.item_name, "description": found_item.item_name, "delivery_date":order_delivery_date, "uom": woocommerce_settings.uom or _("Nos"), "qty": item.get("quantity"), "rate": item.get("price"), "warehouse": woocommerce_settings.warehouse or "Stores" + " - " + company_abbr }) add_tax_details(new_sales_order,ordered_items_tax,"Ordered Item tax",0) # shipping_details = fd.get("shipping_lines") # used for detailed order shipping_total = fd.get("shipping_total") shipping_tax = fd.get("shipping_tax") add_tax_details(new_sales_order,shipping_tax,"Shipping Tax",1) add_tax_details(new_sales_order,shipping_total,"Shipping Total",1) new_sales_order.submit() dataent.db.commit()