def handle_exception(e): http_status_code = getattr(e, "http_status_code", 500) if (http_status_code==500 and isinstance(e, MySQLdb.OperationalError) and e.args[0] in (1205, 1213)): # 1205 = lock wait timeout # 1213 = deadlock # code 409 represents conflict http_status_code = 508 if frappe.local.is_ajax or 'application/json' in frappe.local.request.headers.get('Accept', ''): response = frappe.utils.response.report_error(http_status_code) else: traceback = "<pre>"+frappe.get_traceback()+"</pre>" if frappe.local.flags.disable_traceback: traceback = "" frappe.respond_as_web_page("Server Error", traceback, http_status_code=http_status_code) response = frappe.website.render.render("message", http_status_code=http_status_code) if e.__class__ == frappe.AuthenticationError: if hasattr(frappe.local, "login_manager"): frappe.local.login_manager.clear_cookies() if http_status_code >= 500: frappe.logger().error('Request Error', exc_info=True) make_error_snapshot(e) return response
def get_express_checkout_details(token): try: doc = frappe.get_doc("PayPal Settings") doc.setup_sandbox_env(token) params, url = doc.get_paypal_params_and_url() params.update({ "METHOD": "GetExpressCheckoutDetails", "TOKEN": token }) response = make_post_request(url, data=params) if response.get("ACK")[0] != "Success": frappe.respond_as_web_page(_("Something went wrong"), _("Looks like something went wrong during the transaction. Since we haven't confirmed the payment, Paypal will automatically refund you this amount. If it doesn't, please send us an email and mention the Correlation ID: {0}.").format(response.get("CORRELATIONID", [None])[0]), indicator_color='red', http_status_code=frappe.ValidationError.http_status_code) return update_integration_request_status(token, { "payerid": response.get("PAYERID")[0], "payer_email": response.get("EMAIL")[0] }, "Authorized") frappe.local.response["type"] = "redirect" frappe.local.response["location"] = get_url( \ "/api/method/frappe.integrations.doctype.paypal_settings.paypal_settings.confirm_payment?token={0}".format(token)) except Exception: frappe.log_error(frappe.get_traceback())
def get_express_checkout_details(token): params = get_paypal_params() params.update({ "METHOD": "GetExpressCheckoutDetails", "TOKEN": token }) response = get_api_response(params) if not response["success"]: paypal_log(response, params) frappe.db.commit() frappe.respond_as_web_page(_("Something went wrong"), _("Looks like something went wrong during the transaction. Since we haven't confirmed the payment, Paypal will automatically refund you this amount. If it doesn't, please send us an email and mention the Correlation ID: {0}.").format(response.get("CORRELATIONID", [None])[0]), success=False, http_status_code=frappe.ValidationError.http_status_code) return paypal_express_payment = frappe.get_doc("Paypal Express Payment", token) paypal_express_payment.payerid = response.get("PAYERID")[0] paypal_express_payment.payer_email = response.get("EMAIL")[0] paypal_express_payment.status = "Verified" paypal_express_payment.save(ignore_permissions=True) frappe.db.commit() frappe.local.response["type"] = "redirect" frappe.local.response["location"] = get_url( \ "/api/method/paypal_integration.express_checkout.confirm_payment?token="+paypal_express_payment.token)
def sign_up(email, full_name, redirect_to): user = frappe.db.get("User", {"email": email}) if user: if user.disabled: return _("Registered but disabled.") else: return _("Already Registered") else: if frappe.db.sql("""select count(*) from tabUser where HOUR(TIMEDIFF(CURRENT_TIMESTAMP, TIMESTAMP(modified)))=1""")[0][0] > 300: frappe.respond_as_web_page(_('Temperorily Disabled'), _('Too many users signed up recently, so the registration is disabled. Please try back in an hour'), http_status_code=429) from frappe.utils import random_string user = frappe.get_doc({ "doctype":"User", "email": email, "first_name": full_name, "enabled": 1, "new_password": random_string(10), "user_type": "Website User" }) user.flags.ignore_permissions = True user.insert() if redirect_to: frappe.cache().hset('redirect_after_login', user.name, redirect_to) if user.flags.email_sent: return _("Please check your email for verification") else: return _("Please ask your administrator to verify your sign-up")
def dropbox_auth_finish(return_access_token=False): app_details = get_dropbox_settings(redirect_uri=True) callback = frappe.form_dict close = '<p class="text-muted">' + _('Please close this window') + '</p>' dropbox_oauth_flow = dropbox.DropboxOAuth2Flow( app_details["app_key"], app_details["app_secret"], app_details["rediret_uri"], { 'dropbox-auth-csrf-token': callback.state }, "dropbox-auth-csrf-token" ) if callback.state or callback.code: token = dropbox_oauth_flow.finish({'state': callback.state, 'code': callback.code}) if return_access_token and token.access_token: return token.access_token, callback.state set_dropbox_access_token(token.access_token) else: frappe.respond_as_web_page(_("Dropbox Setup"), _("Illegal Access Token. Please try again") + close, indicator_color='red', http_status_code=frappe.AuthenticationError.http_status_code) frappe.respond_as_web_page(_("Dropbox Setup"), _("Dropbox access is approved!") + close, indicator_color='green')
def return_success_page(doc): frappe.respond_as_web_page(_("Success"), _("{0}: {1} is set to state {2}".format( doc.get('doctype'), frappe.bold(doc.get('name')), frappe.bold(get_doc_workflow_state(doc)) )), indicator_color='green')
def get_checkout_url(**kwargs): try: return frappe.get_doc("Razorpay Settings").get_payment_url(**kwargs) except Exception: frappe.respond_as_web_page(_("Something went wrong"), _("Looks like something is wrong with this site's Razorpay configuration. Don't worry! No payment has been made."), success=False, http_status_code=frappe.ValidationError.http_status_code)
def get_payment_url(doc, method): if doc.docstatus not in [0, 2]: if doc.gateway == "PayPal": set_express_checkout(doc.amount, doc.currency, {"doctype": doc.doctype, "docname": doc.name}) else: frappe.respond_as_web_page(_("Invalid Payment Request"), _("Payment Request has been canceled by vendor"), success=False, http_status_code=frappe.ValidationError.http_status_code)
def return_link_expired_page(doc, doc_workflow_state): frappe.respond_as_web_page(_("Link Expired"), _("Document {0} has been set to state {1} by {2}" .format( frappe.bold(doc.get('name')), frappe.bold(doc_workflow_state), frappe.bold(frappe.get_value('User', doc.get("modified_by"), 'full_name')) )), indicator_color='blue')
def update_oauth_user(user, data, provider): if isinstance(data.get("location"), dict): data["location"] = data.get("location").get("name") save = False if not frappe.db.exists("User", user): # is signup disabled? if frappe.utils.cint(frappe.db.get_single_value("Website Settings", "disable_signup")): raise SignupDisabledError save = True user = frappe.new_doc("User") user.update({ "doctype":"User", "first_name": get_first_name(data), "last_name": get_last_name(data), "email": data["email"], "gender": (data.get("gender") or "").title(), "enabled": 1, "new_password": frappe.generate_hash(data["email"]), "location": data.get("location"), "user_type": "Website User", "user_image": data.get("picture") or data.get("avatar_url") }) else: user = frappe.get_doc("User", user) if not user.enabled: frappe.respond_as_web_page(_('Not Allowed'), _('User {0} is disabled').format(user.email)) return False if provider=="facebook" and not user.get("fb_userid"): save = True user.update({ "fb_username": data.get("username"), "fb_userid": data["id"], "user_image": "https://graph.facebook.com/{id}/picture".format(id=data["id"]) }) elif provider=="google" and not user.get("google_userid"): save = True user.google_userid = data["id"] elif provider=="github" and not user.get("github_userid"): save = True user.github_userid = data["id"] user.github_username = data["login"] elif provider=="frappe" and not user.get("frappe_userid"): save = True user.frappe_userid = data["sub"] if save: user.flags.ignore_permissions = True user.flags.no_welcome_mail = True user.save()
def get_checkout_url(**kwargs): try: doc = frappe.get_doc("PayPal Settings") return doc.get_payment_url(**kwargs) except Exception: frappe.respond_as_web_page(_("Something went wrong"), _("Looks like something is wrong with this site's Paypal configuration. Don't worry! No payment has been made from your Paypal account."), success=False, http_status_code=frappe.ValidationError.http_status_code)
def get_payment_url(doc, method): if doc.docstatus == 1: if doc.payment_gateway == "Razorpay": frappe.local.response["type"] = "redirect" frappe.local.response["location"] = "./razorpay_checkout?doctype=Payment Request&docname={0}".format(doc.name) else: frappe.respond_as_web_page(_("Invalid Payment Request"), _("Payment Request has been canceled by vendor"), success=False, http_status_code=frappe.ValidationError.http_status_code)
def login_via_token(login_token): sid = frappe.cache().get_value("login_token:{0}".format(login_token), expires=True) if not sid: frappe.respond_as_web_page(_("Invalid Request"), _("Invalid Login Token"), http_status_code=417) return frappe.local.form_dict.sid = sid frappe.local.login_manager = LoginManager() redirect_post_login(desk_user = frappe.db.get_value("User", frappe.session.user, "user_type")=="System User")
def callback(*args, **kwargs): migrator = frappe.get_doc("QuickBooks Migrator") migrator.set_indicator("Connecting to QuickBooks") migrator.code = kwargs.get("code") migrator.quickbooks_company_id = kwargs.get("realmId") migrator.save() migrator.get_tokens() frappe.db.commit() migrator.set_indicator("Connected to QuickBooks") # We need this page to automatically close afterwards frappe.respond_as_web_page("Quickbooks Authentication", html="<script>window.close()</script>")
def get_checkout_url(**kwargs): try: if kwargs.get('payment_gateway'): doc = frappe.get_doc("{0} Settings".format(kwargs.get('payment_gateway'))) return doc.get_payment_url(**kwargs) else: raise Exception except Exception: frappe.respond_as_web_page(_("Something went wrong"), _("Looks like something is wrong with this site's payment gateway configuration. No payment has been made."), indicator_color='red', http_status_code=frappe.ValidationError.http_status_code)
def handle_exception(e): response = None http_status_code = getattr(e, "http_status_code", 500) return_as_message = False if frappe.local.is_ajax or 'application/json' in frappe.get_request_header('Accept'): # handle ajax responses first # if the request is ajax, send back the trace or error message response = frappe.utils.response.report_error(http_status_code) elif (http_status_code==500 and isinstance(e, MySQLdb.OperationalError) and e.args[0] in (1205, 1213)): # 1205 = lock wait timeout # 1213 = deadlock # code 409 represents conflict http_status_code = 508 elif http_status_code==401: frappe.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: frappe.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: frappe.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>"+frappe.get_traceback()+"</pre>" if frappe.local.flags.disable_traceback: traceback = "" frappe.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__ == frappe.AuthenticationError: if hasattr(frappe.local, "login_manager"): frappe.local.login_manager.clear_cookies() if http_status_code >= 500: frappe.logger().error('Request Error', exc_info=True) make_error_snapshot(e) if return_as_message: response = frappe.website.render.render("message", http_status_code=http_status_code) return response
def verify_request(): """Verify if the incoming signed request if it is correct.""" query_string = frappe.request.query_string if hasattr(frappe.request, "query_string") \ else frappe.local.flags.signed_query_string params, signature = query_string.split("&_signature=") given_signature = hmac.new(params.encode("utf-8")) given_signature.update(get_secret()) valid = signature == given_signature.hexdigest() if not valid: frappe.respond_as_web_page(_("Invalid Link"), _("This link is invalid or expired. Please make sure you have pasted correctly.")) return valid
def set_express_checkout(amount, currency="USD", data=None): validate_transaction_currency(currency) if not isinstance(data, basestring): data = frappe.as_json(data or "{}") response = execute_set_express_checkout(amount, currency) if not response["success"]: paypal_log(response) frappe.db.commit() frappe.respond_as_web_page(_("Something went wrong"), _("Looks like something is wrong with this site's Paypal configuration. Don't worry! No payment has been made from your Paypal account."), success=False, http_status_code=frappe.ValidationError.http_status_code) return paypal_settings = get_paypal_settings() if paypal_settings.paypal_sandbox: return_url = "https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token={0}" else: return_url = "https://www.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token={0}" token = response.get("TOKEN")[0] paypal_express_payment = frappe.get_doc({ "doctype": "Paypal Express Payment", "status": "Started", "amount": amount, "currency": currency, "token": token, "data": data, "correlation_id": response.get("CORRELATIONID")[0] }) if data: if isinstance(data, basestring): data = json.loads(data) if data.get("doctype") and data.get("docname"): paypal_express_payment.reference_doctype = data.get("doctype") paypal_express_payment.reference_docname = data.get("docname") paypal_express_payment.insert(ignore_permissions = True) frappe.db.commit() frappe.local.response["type"] = "redirect" frappe.local.response["location"] = return_url.format(token)
def return_action_confirmation_page(doc, action, action_link, alert_doc_change=False): template_params = { 'title': doc.get('name'), 'doctype': doc.get('doctype'), 'docname': doc.get('name'), 'action': action, 'action_link': action_link, 'alert_doc_change': alert_doc_change } template_params['pdf_link'] = get_pdf_link(doc.get('doctype'), doc.get('name')) frappe.respond_as_web_page(None, None, indicator_color="blue", template="confirm_workflow_action", context=template_params)
def login_oauth_user(data=None, provider=None, email_id=None, key=None): if email_id and key: data = json.loads(frappe.db.get_temp(key)) data["email"] = email_id elif not (data.get("email") and get_first_name(data)) and not frappe.db.exists("User", data.get("email")): # ask for user email key = frappe.db.set_temp(json.dumps(data)) frappe.db.commit() frappe.local.response["type"] = "redirect" frappe.local.response["location"] = "/complete_signup?key=" + key return user = data["email"] try: update_oauth_user(user, data, provider) except SignupDisabledError: return frappe.respond_as_web_page("Signup is Disabled", "Sorry. Signup from Website is disabled.", success=False, http_status_code=403) frappe.local.login_manager.user = user frappe.local.login_manager.post_login() # redirect! frappe.local.response["type"] = "redirect" # the #desktop is added to prevent a facebook redirect bug frappe.local.response["location"] = "/desk#desktop" if frappe.local.response.get('message') == 'Logged In' else "/" # because of a GET request! frappe.db.commit()
def confirm_subscription(email): if not verify_request(): return if not frappe.db.exists("Email Group", _("Website")): frappe.get_doc({ "doctype": "Email Group", "title": _("Website") }).insert(ignore_permissions=True) frappe.flags.ignore_permissions = True add_subscribers(_("Website"), email) frappe.db.commit() frappe.respond_as_web_page(_("Confirmed"), _("{0} has been successfully added to our Email Group.").format(email))
def authorize(*args, **kwargs): #Fetch provider URL from settings oauth_settings = get_oauth_settings() params = get_urlparams_from_kwargs(kwargs) request_url = urlparse(frappe.request.url) success_url = request_url.scheme + "://" + request_url.netloc + "/api/method/frappe.integration_broker.oauth2.approve?" + params failure_url = frappe.form_dict["redirect_uri"] + "?error=access_denied" if frappe.session['user']=='Guest': #Force login, redirect to preauth again. frappe.local.response["type"] = "redirect" frappe.local.response["location"] = "/login?redirect-to=/api/method/frappe.integration_broker.oauth2.authorize?" + quote(params) elif frappe.session['user']!='Guest': try: r = frappe.request uri = r.url http_method = r.method body = r.get_data() headers = r.headers scopes, credentials = oauth_server.validate_authorization_request(uri, http_method, body, headers) skip_auth = frappe.db.get_value("OAuth Client", credentials['client_id'], "skip_authorization") unrevoked_tokens = frappe.get_all("OAuth Bearer Token", filters={"status":"Active"}) if skip_auth or (oauth_settings["skip_authorization"] == "Auto" and len(unrevoked_tokens)): frappe.local.response["type"] = "redirect" frappe.local.response["location"] = success_url else: #Show Allow/Deny screen. response_html_params = frappe._dict({ "client_id": frappe.db.get_value("OAuth Client", kwargs['client_id'], "app_name"), "success_url": success_url, "failure_url": failure_url, "details": scopes }) resp_html = frappe.render_template("templates/includes/oauth_confirmation.html", response_html_params) frappe.respond_as_web_page("Confirm Access", resp_html) except FatalClientError as e: return e except OAuth2Error as e: return e
def login_oauth_user(data=None, provider=None, state=None, email_id=None, key=None, generate_login_token=False): # NOTE: This could lead to security issue as the signed in user can type any email address in complete_signup # if email_id and key: # data = json.loads(frappe.db.get_temp(key)) # # What if data is missing because of an invalid key # data["email"] = email_id # # elif not (data.get("email") and get_first_name(data)) and not frappe.db.exists("User", data.get("email")): # # ask for user email # key = frappe.db.set_temp(json.dumps(data)) # frappe.db.commit() # frappe.local.response["type"] = "redirect" # frappe.local.response["location"] = "/complete_signup?key=" + key # return # json.loads data and state if isinstance(data, basestring): data = json.loads(data) if isinstance(state, basestring): state = json.loads(state) if not (state and state["token"]): frappe.respond_as_web_page(_("Invalid Request"), _("Token is missing"), http_status_code=417) return token = frappe.cache().get_value("{0}:{1}".format(provider, state["token"]), expires=True) if not token: frappe.respond_as_web_page(_("Invalid Request"), _("Invalid Token"), http_status_code=417) return user = data["email"] if not user: frappe.respond_as_web_page(_("Invalid Request"), _("Please ensure that your profile has an email address")) return try: if update_oauth_user(user, data, provider) is False: return except SignupDisabledError: return frappe.respond_as_web_page( "Signup is Disabled", "Sorry. Signup from Website is disabled.", success=False, http_status_code=403 ) frappe.local.login_manager.user = user frappe.local.login_manager.post_login() # because of a GET request! frappe.db.commit() if frappe.utils.cint(generate_login_token): login_token = frappe.generate_hash(length=32) frappe.cache().set_value("login_token:{0}".format(login_token), frappe.local.session.sid, expires_in_sec=120) frappe.response["login_token"] = login_token else: redirect_post_login(desk_user=frappe.local.response.get("message") == "Logged In")
def execute_cmd(cmd, from_async=False): """execute a request as python module""" for hook in frappe.get_hooks("override_whitelisted_methods", {}).get(cmd, []): # override using the first hook cmd = hook break try: method = get_attr(cmd) except: frappe.respond_as_web_page(title='Invalid Method', html='Method not found', indicator_color='red', http_status_code=404) return if from_async: method = method.queue is_whitelisted(method) return frappe.call(method, **frappe.form_dict)
def verify_request(): """Verify if the incoming signed request if it is correct.""" query_string = frappe.safe_decode(frappe.local.flags.signed_query_string or \ getattr(frappe.request, 'query_string', None)) valid = False signature_string = '&_signature=' if signature_string in query_string: params, signature = query_string.split(signature_string) given_signature = hmac.new(params.encode('utf-8')) given_signature.update(get_secret().encode()) valid = signature == given_signature.hexdigest() if not valid: frappe.respond_as_web_page(_("Invalid Link"), _("This link is invalid or expired. Please make sure you have pasted correctly.")) return valid
def login_oauth_user(data, provider=None): if data.has_key("email"): user = data["email"] try: update_oauth_user(user, data, provider) except SignupDisabledError: return frappe.respond_as_web_page("Signup is Disabled", "Sorry. Signup from Website is disabled.", success=False, http_status_code=403) frappe.local.login_manager.user = user frappe.local.login_manager.post_login() frappe.db.commit()
def dropbox_callback(oauth_token=None, not_approved=False): doc = frappe.get_doc("Dropbox Settings") close = '<p class="text-muted">' + _('Please close this window') + '</p>' if not not_approved: if doc.get_password(fieldname="dropbox_access_key", raise_exception=False)==oauth_token: sess = doc.get_dropbox_session() sess.set_request_token(doc.get_password(fieldname="dropbox_access_key", raise_exception=False), doc.get_password(fieldname="dropbox_access_secret", raise_exception=False)) access_token = sess.obtain_access_token() frappe.db.set_value("Dropbox Settings", None, "dropbox_access_key", access_token.key) frappe.db.set_value("Dropbox Settings", None, "dropbox_access_secret", access_token.secret) frappe.db.commit() else: frappe.respond_as_web_page(_("Dropbox Setup"), _("Illegal Access Token. Please try again") + close, success=False, http_status_code=frappe.AuthenticationError.http_status_code) else: frappe.respond_as_web_page(_("Dropbox Setup"), _("You did not apporve Dropbox Access.") + close, success=False, http_status_code=frappe.AuthenticationError.http_status_code) frappe.respond_as_web_page(_("Dropbox Setup"), _("Dropbox access is approved!") + close, success=False, http_status_code=frappe.AuthenticationError.http_status_code)
def build_response(self): self.writer = UnicodeWriter() self.name_field = 'parent' if self.parent_doctype != self.doctype else 'name' if self.template: self.add_main_header() self.writer.writerow(['']) self.tablerow = [self.data_keys.doctype] self.labelrow = [_("Column Labels:")] self.fieldrow = [self.data_keys.columns] self.mandatoryrow = [_("Mandatory:")] self.typerow = [_('Type:')] self.inforow = [_('Info:')] self.columns = [] self.build_field_columns(self.doctype) if self.all_doctypes: for d in self.child_doctypes: self.append_empty_field_column() if (self.select_columns and self.select_columns.get(d['doctype'], None)) or not self.select_columns: # if atleast one column is selected for this doctype self.build_field_columns(d['doctype'], d['parentfield']) self.add_field_headings() self.add_data() if self.with_data and not self.data: frappe.respond_as_web_page(_('No Data'), _('There is no data to be exported'), indicator_color='orange') if self.file_type == 'Excel': self.build_response_as_excel() else: # write out response as a type csv frappe.response['result'] = cstr(self.writer.getvalue()) frappe.response['type'] = 'csv' frappe.response['doctype'] = self.doctype
def login_oauth_user(data, provider=None): user = data["email"] try: update_oauth_user(user, data, provider) except SignupDisabledError: return frappe.respond_as_web_page( "Signup is Disabled", "Sorry. Signup from Website is disabled.", success=False, http_status_code=403 ) frappe.local.login_manager.user = user frappe.local.login_manager.post_login() # redirect! frappe.local.response["type"] = "redirect" # the #desktop is added to prevent a facebook redirect bug frappe.local.response["location"] = "/desk#desktop" if frappe.local.response.get("message") == "Logged In" else "/" # because of a GET request! frappe.db.commit()
def dropbox_callback(oauth_token=None, not_approved=False): doc = frappe.get_doc("Dropbox Settings") if not not_approved: if doc.get_password(fieldname="dropbox_access_key", raise_exception=False)==oauth_token: sess = doc.get_dropbox_session() sess.set_request_token(doc.get_password(fieldname="dropbox_access_key", raise_exception=False), doc.get_password(fieldname="dropbox_access_secret", raise_exception=False)) access_token = sess.obtain_access_token() frappe.db.set_value("Dropbox Settings", None, "dropbox_access_key", access_token.key) frappe.db.set_value("Dropbox Settings", None, "dropbox_access_secret", access_token.secret) frappe.db.commit() else: frappe.respond_as_web_page(_("Dropbox Approval"), _("Illegal Access Token Please try again. <p>Please close this window.</p"), success=False, http_status_code=frappe.AuthenticationError.http_status_code) else: frappe.respond_as_web_page(_("Dropbox Approval"), _("Dropbox Access not approved. <p>Please close this window.</p"), success=False, http_status_code=frappe.AuthenticationError.http_status_code) frappe.respond_as_web_page(_("Dropbox Approval"), _("Dropbox access allowed. <p>Please close this window.</p"), success=False, http_status_code=frappe.AuthenticationError.http_status_code)
def return_unsubscribed_page(email): frappe.respond_as_web_page(_("Unsubscribed"), _("{0} has been successfully unsubscribed from this list.").format(email))
and isinstance(e, MySQLdb.OperationalError) and e.args[0] in (1205, 1213)): # 1205 = lock wait timeout # 1213 = deadlock # code 409 represents conflict http_status_code = 508 if frappe.local.is_ajax or 'application/json' in request.headers.get('Accept', ''): response = frappe.utils.response.report_error(http_status_code) else: traceback = "<pre>"+frappe.get_traceback()+"</pre>" if frappe.local.flags.disable_traceback: traceback = "" frappe.respond_as_web_page("Server Error", traceback, http_status_code=http_status_code) response = frappe.website.render.render("message", http_status_code=http_status_code) if e.__class__ == frappe.AuthenticationError: if hasattr(frappe.local, "login_manager"): frappe.local.login_manager.clear_cookies() if http_status_code==500: logger.error('Request Error') else: if frappe.local.request.method in ("POST", "PUT") and frappe.db: if frappe.db.transaction_writes: frappe.db.commit() rollback = False
def handle_session_stopped(): frappe.respond_as_web_page(_("Updating"), _("Your system is being updated. Please refresh again after a few moments."), http_status_code=503, indicator_color='orange', fullpage = True, primary_action=None) return frappe.website.render.render("message", http_status_code=503)
def search_widget(doctype, txt, query=None, searchfield=None, start=0, page_length=20, filters=None, filter_fields=None, as_dict=False, reference_doctype=None, ignore_user_permissions=False): start = cint(start) if isinstance(filters, str): filters = json.loads(filters) if searchfield: sanitize_searchfield(searchfield) if not searchfield: searchfield = "name" standard_queries = frappe.get_hooks().standard_queries or {} if query and query.split()[0].lower() != "select": # by method try: is_whitelisted(frappe.get_attr(query)) frappe.response["values"] = frappe.call(query, doctype, txt, searchfield, start, page_length, filters, as_dict=as_dict) except frappe.exceptions.PermissionError as e: if frappe.local.conf.developer_mode: raise e else: frappe.respond_as_web_page(title='Invalid Method', html='Method not found', indicator_color='red', http_status_code=404) return except Exception as e: raise e elif not query and doctype in standard_queries: # from standard queries search_widget(doctype, txt, standard_queries[doctype][0], searchfield, start, page_length, filters) else: meta = frappe.get_meta(doctype) if query: frappe.throw(_("This query style is discontinued")) # custom query # frappe.response["values"] = frappe.db.sql(scrub_custom_query(query, searchfield, txt)) else: if isinstance(filters, dict): filters_items = filters.items() filters = [] for f in filters_items: if isinstance(f[1], (list, tuple)): filters.append([doctype, f[0], f[1][0], f[1][1]]) else: filters.append([doctype, f[0], "=", f[1]]) if filters == None: filters = [] or_filters = [] # build from doctype if txt: search_fields = ["name"] if meta.title_field: search_fields.append(meta.title_field) if meta.search_fields: search_fields.extend(meta.get_search_fields()) for f in search_fields: fmeta = meta.get_field(f.strip()) if (doctype not in UNTRANSLATED_DOCTYPES) and ( f == "name" or (fmeta and fmeta.fieldtype in [ "Data", "Text", "Small Text", "Long Text", "Link", "Select", "Read Only", "Text Editor" ])): or_filters.append( [doctype, f.strip(), "like", "%{0}%".format(txt)]) if meta.get("fields", { "fieldname": "enabled", "fieldtype": "Check" }): filters.append([doctype, "enabled", "=", 1]) if meta.get("fields", { "fieldname": "disabled", "fieldtype": "Check" }): filters.append([doctype, "disabled", "!=", 1]) # format a list of fields combining search fields and filter fields fields = get_std_fields_list(meta, searchfield or "name") if filter_fields: fields = list(set(fields + json.loads(filter_fields))) formatted_fields = [ '`tab%s`.`%s`' % (meta.name, f.strip()) for f in fields ] # find relevance as location of search term from the beginning of string `name`. used for sorting results. formatted_fields.append( """locate({_txt}, `tab{doctype}`.`name`) as `_relevance`""". format(_txt=frappe.db.escape( (txt or "").replace("%", "").replace("@", "")), doctype=doctype)) # In order_by, `idx` gets second priority, because it stores link count from frappe.model.db_query import get_order_by order_by_based_on_meta = get_order_by(doctype, meta) # 2 is the index of _relevance column order_by = "_relevance, {0}, `tab{1}`.idx desc".format( order_by_based_on_meta, doctype) ptype = 'select' if frappe.only_has_select_perm( doctype) else 'read' ignore_permissions = True if doctype == "DocType" else ( cint(ignore_user_permissions) and has_permission(doctype, ptype=ptype)) if doctype in UNTRANSLATED_DOCTYPES: page_length = None values = frappe.get_list(doctype, filters=filters, fields=formatted_fields, or_filters=or_filters, limit_start=start, limit_page_length=page_length, order_by=order_by, ignore_permissions=ignore_permissions, reference_doctype=reference_doctype, as_list=not as_dict, strict=False) if doctype in UNTRANSLATED_DOCTYPES: # Filtering the values array so that query is included in very element values = (v for v in values if re.search( f"{re.escape(txt)}.*", _(v.name if as_dict else v[0]), re.IGNORECASE)) # Sorting the values array so that relevant results always come first # This will first bring elements on top in which query is a prefix of element # Then it will bring the rest of the elements and sort them in lexicographical order values = sorted(values, key=lambda x: relevance_sorter(x, txt, as_dict)) # remove _relevance from results if as_dict: for r in values: r.pop("_relevance") frappe.response["values"] = values else: frappe.response["values"] = [r[:-1] for r in values]
def return_unsubscribed_page(email, doctype, name): frappe.respond_as_web_page( _("Unsubscribed"), _("{0} has left the conversation in {1} {2}").format( email, _(doctype), name), indicator_color='green')
except Exception, e: http_status_code = getattr(e, "http_status_code", 500) if (http_status_code==500 and isinstance(e, MySQLdb.OperationalError) and e.args[0] in (1205, 1213)): # 1205 = lock wait timeout # 1213 = deadlock # code 409 represents conflict http_status_code = 409 if frappe.local.is_ajax or 'application/json' in request.headers.get('Accept', ''): response = frappe.utils.response.report_error(http_status_code) else: frappe.respond_as_web_page("Server Error", "<pre>"+frappe.get_traceback()+"</pre>", http_status_code=http_status_code) response = frappe.website.render.render("message", http_status_code=http_status_code) if e.__class__ == frappe.AuthenticationError: if hasattr(frappe.local, "login_manager"): frappe.local.login_manager.clear_cookies() if http_status_code==500: logger.error('Request Error') else: if frappe.local.request.method in ("POST", "PUT") and frappe.db: frappe.db.commit() rollback = False
def login_oauth_user(data=None, provider=None, state=None, email_id=None, key=None, generate_login_token=False): # NOTE: This could lead to security issue as the signed in user can type any email address in complete_signup # if email_id and key: # data = json.loads(frappe.db.get_temp(key)) # # What if data is missing because of an invalid key # data["email"] = email_id # # elif not (data.get("email") and get_first_name(data)) and not frappe.db.exists("User", data.get("email")): # # ask for user email # key = frappe.db.set_temp(json.dumps(data)) # frappe.db.commit() # frappe.local.response["type"] = "redirect" # frappe.local.response["location"] = "/complete_signup?key=" + key # return # json.loads data and state if isinstance(data, string_types): data = json.loads(data) if isinstance(state, string_types): state = json.loads(state) if not (state and state["token"]): frappe.respond_as_web_page(_("Invalid Request"), _("Token is missing"), http_status_code=417) return token = frappe.cache().get_value("{0}:{1}".format(provider, state["token"]), expires=True) if not token: frappe.respond_as_web_page(_("Invalid Request"), _("Invalid Token"), http_status_code=417) return user = get_email(data) if not user: frappe.respond_as_web_page( _("Invalid Request"), _("Please ensure that your profile has an email address")) return try: if update_oauth_user(user, data, provider) is False: return except SignupDisabledError: return frappe.respond_as_web_page( "Signup is Disabled", "Sorry. Signup from Website is disabled.", success=False, http_status_code=403) frappe.local.login_manager.user = user frappe.local.login_manager.post_login() # because of a GET request! frappe.db.commit() if frappe.utils.cint(generate_login_token): login_token = frappe.generate_hash(length=32) frappe.cache().set_value("login_token:{0}".format(login_token), frappe.local.session.sid, expires_in_sec=120) frappe.response["login_token"] = login_token else: redirect_post_login( desk_user=frappe.local.response.get('message') == 'Logged In')
def web_logout(): frappe.local.login_manager.logout() frappe.db.commit() frappe.respond_as_web_page("Logged Out", """<p style="margin-top:10%;text-align: center;">You have been logged out.</p> <p style="text-align: center;"><a href='index'>Back to Home</a></p>""")
def web_logout(): frappe.local.login_manager.logout() frappe.db.commit() frappe.respond_as_web_page( _("Logged Out"), """<p>""" + _("You have been logged out.") + """</p> <p><a href='index'>""" + _("Back to Home") + """</a></p>""")
def update_oauth_user(user, data, provider): if isinstance(data.get("location"), dict): data["location"] = data.get("location").get("name") save = False if not frappe.db.exists("User", user): # is signup disabled? if frappe.utils.cint( frappe.db.get_single_value("Website Settings", "disable_signup")): raise SignupDisabledError save = True user = frappe.new_doc("User") user.update({ "doctype": "User", "first_name": get_first_name(data), "last_name": get_last_name(data), "email": get_email(data), "gender": (data.get("gender") or "").title(), "enabled": 1, "new_password": frappe.generate_hash(get_email(data)), "location": data.get("location"), "user_type": "Website User", "user_image": data.get("picture") or data.get("avatar_url") }) else: user = frappe.get_doc("User", user) if not user.enabled: frappe.respond_as_web_page( _('Not Allowed'), _('User {0} is disabled').format(user.email)) return False if provider == "facebook" and not user.get_social_login_userid(provider): save = True user.set_social_login_userid(provider, userid=data["id"], username=data.get("username")) user.update({ "user_image": "https://graph.facebook.com/{id}/picture".format(id=data["id"]) }) elif provider == "google" and not user.get_social_login_userid(provider): save = True user.set_social_login_userid(provider, userid=data["id"]) elif provider == "github" and not user.get_social_login_userid(provider): save = True user.set_social_login_userid(provider, userid=data["id"], username=data.get("login")) elif provider == "frappe" and not user.get_social_login_userid(provider): save = True user.set_social_login_userid(provider, userid=data["sub"]) elif provider == "office_365" and not user.get_social_login_userid( provider): save = True user.set_social_login_userid(provider, userid=data["sub"]) elif provider == "salesforce" and not user.get_social_login_userid( provider): save = True user.set_social_login_userid(provider, userid="/".join( data["sub"].split("/")[-2:])) elif provider == "fairlogin" and not user.get_social_login_userid( provider): save = True user.set_social_login_userid(provider, userid=data["preferred_username"]) if save: user.flags.ignore_permissions = True user.flags.no_welcome_mail = True user.save()
def web_logout(): frappe.local.login_manager.logout() frappe.db.commit() frappe.respond_as_web_page("Logged Out", """<p><a href="/index" class="text-muted">Back to Home</a></p>""")
def web_logout(): frappe.local.login_manager.logout() frappe.db.commit() frappe.respond_as_web_page(_("Logged Out"), _("You have been successfully logged out"), indicator_color='green')
def return_unsubscribed_page(email, name): frappe.respond_as_web_page( _("Unsubscribed from Newsletter"), _("<b>{0}</b> has been successfully unsubscribed from this mailing list." ).format(email, name), indicator_color='green')
def login_oauth_user(data=None, provider=None, state=None, email_id=None, key=None, generate_login_token=False): if not ((data and provider and state) or (email_id and key)): frappe.respond_as_web_page(_("Invalid Request"), _("Missing parameters for login"), http_status_code=417) return _login_oauth_user(data, provider, state, email_id, key, generate_login_token)
def handle_exception(e): response = None http_status_code = getattr(e, "http_status_code", 500) return_as_message = False if frappe.get_request_header('Accept') and ( frappe.local.is_ajax or 'application/json' in frappe.get_request_header('Accept')): # handle ajax responses first # if the request is ajax, send back the trace or error message response = frappe.utils.response.report_error(http_status_code) elif (http_status_code == 500 and (frappe.db and isinstance(e, frappe.db.InternalError)) and (frappe.db and (frappe.db.is_deadlocked(e) or frappe.db.is_timedout(e)))): http_status_code = 508 elif http_status_code == 401: frappe.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: frappe.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: frappe.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 elif http_status_code == 429: response = frappe.rate_limiter.respond() else: traceback = "<pre>" + sanitize_html(frappe.get_traceback()) + "</pre>" if frappe.local.flags.disable_traceback: traceback = "" frappe.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__ == frappe.AuthenticationError: if hasattr(frappe.local, "login_manager"): frappe.local.login_manager.clear_cookies() if http_status_code >= 500: frappe.logger().error('Request Error', exc_info=True) make_error_snapshot(e) if return_as_message: response = frappe.website.render.render( "message", http_status_code=http_status_code) return response
def handle_exception(e): response = None http_status_code = getattr(e, "http_status_code", 500) return_as_message = False if frappe.local.is_ajax or 'application/json' in frappe.local.request.headers.get( 'Accept', ''): # handle ajax responses first # if the request is ajax, send back the trace or error message response = frappe.utils.response.report_error(http_status_code) elif (http_status_code == 500 and isinstance(e, MySQLdb.OperationalError) and e.args[0] in (1205, 1213)): # 1205 = lock wait timeout # 1213 = deadlock # code 409 represents conflict http_status_code = 508 elif http_status_code == 401: frappe.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: frappe.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: frappe.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>" + frappe.get_traceback() + "</pre>" if frappe.local.flags.disable_traceback: traceback = "" frappe.respond_as_web_page("Server Error", traceback, http_status_code=http_status_code, indicator_color='red') return_as_message = True if e.__class__ == frappe.AuthenticationError: if hasattr(frappe.local, "login_manager"): frappe.local.login_manager.clear_cookies() if http_status_code >= 500: frappe.logger().error('Request Error', exc_info=True) make_error_snapshot(e) if return_as_message: response = frappe.website.render.render( "message", http_status_code=http_status_code) return response
def sign_up(email, full_name, dob, phone_number, address, guardian_name, redirect_to): if not is_signup_enabled(): frappe.throw(_('Sign Up is disabled'), title='Not Allowed') user = frappe.db.get("User", {"email": email}) if user: if user.disabled: return 0, _("Registered but disabled") else: return 0, _("Already Registered") else: if frappe.db.sql("""select count(*) from tabUser where HOUR(TIMEDIFF(CURRENT_TIMESTAMP, TIMESTAMP(modified)))=1""")[0][0] > 300: frappe.respond_as_web_page( _('Temperorily Disabled'), _('Too many users signed up recently, so the registration is disabled. Please try back in an hour' ), http_status_code=429) from frappe.utils import random_string import datetime date_format_dict = { "yyyy-mm-dd": "%Y-%m-%d", "dd-mm-yyyy": "%d-%m-%Y", "dd/mm/yyyy": "%d/%m/%Y", "dd.mm.yyyy": "%d.%m.%Y", "mm/dd/yyyy": "%m/%d/%Y", "mm-dd-yyyy": "%m-%d-%Y" } get_date_format_string = date_format_dict["mm-dd-yyyy"] get_system_date_format = frappe.db.get_value("System Settings", None, "date_format") if get_system_date_format in date_format_dict: get_date_format_string = date_format_dict[str( get_system_date_format)] else: frappe.db.set_value("System Settings", None, "date_format", "mm-dd-yyyy") frappe.db.commit() datetime_obj = datetime.datetime.strptime(dob, '%Y-%m-%d').strftime( str(get_date_format_string)) user = frappe.get_doc({ "doctype": "User", "email": email, "first_name": full_name, "birth_date": frappe.utils.getdate(datetime_obj), "phone": phone_number, "address": address, "guardian_name": guardian_name, "enabled": 1, "new_password": random_string(10), "user_type": "Website User" }) user.flags.ignore_permissions = True user.insert() customer = frappe.get_doc({ "doctype": "Customer", "customer_name": full_name, "customer_type": "Individual" }) customer.flags.ignore_permissions = True customer.insert() # set default signup role as per Portal Settings default_role = frappe.db.get_value("Portal Settings", None, "default_role") if default_role: user.add_roles(default_role) # frappe.throw("--- "+ str(redirect_to) + " ---Hello") if redirect_to: frappe.cache().hset('redirect_after_login', user.name, redirect_to) if user.flags.email_sent: return 1, _("Please check your email for verification") else: return 2, _("Please ask your administrator to verify your sign-up")