* [fix] refactor integration services * [fix] patch fix * [fix] added redirect url. * [fix] custom redirect to and reditect message for paypal and service setup information * [minor][fix] remove ldap dependancy from requirementsversion-14
@@ -222,9 +222,8 @@ def get_data(): | |||
}, | |||
{ | |||
"type": "doctype", | |||
"name": "Dropbox Backup", | |||
"description": _("Manage cloud backups on Dropbox"), | |||
"hide_count": True | |||
"name": "Integration Service", | |||
"description": _("Centralize access to Integrations"), | |||
} | |||
] | |||
}, | |||
@@ -176,4 +176,4 @@ bot_parsers = [ | |||
setup_wizard_exception = "frappe.desk.page.setup_wizard.setup_wizard.email_setup_wizard_exception" | |||
before_write_file = "frappe.limits.validate_space_limit" | |||
integration_services = ["PayPal", "Razorpay", "Dropbox Integration", "LDAP Auth"] | |||
integration_services = ["PayPal", "Razorpay", "Dropbox", "LDAP"] |
@@ -1,6 +1,13 @@ | |||
// Copyright (c) 2016, Frappe Technologies and contributors | |||
// For license information, please see license.txt | |||
frappe.provide("frappe.integration_service"); | |||
{% include 'frappe/integrations/doctype/razorpay_settings/razorpay_settings.js' %} | |||
{% include 'frappe/integrations/doctype/paypal_settings/paypal_settings.js' %} | |||
{% include 'frappe/integrations/doctype/dropbox_settings/dropbox_settings.js' %} | |||
{% include 'frappe/integrations/doctype/ldap_settings/ldap_settings.js' %} | |||
frappe.ui.form.on('Integration Service', { | |||
onload: function(frm) { | |||
frappe.call({ | |||
@@ -13,119 +20,36 @@ frappe.ui.form.on('Integration Service', { | |||
refresh: function(frm){ | |||
if (frm.doc.service){ | |||
frm.events.load_js_resouce(frm); | |||
frm.events.setup_custom_buttons(frm); | |||
frm.events.setup_service_details(frm); | |||
} | |||
}, | |||
load_js_resouce: function(frm){ | |||
frappe.call({ | |||
method: 'frappe.integration_broker.doctype.integration_service.integration_service.get_js_resouce', | |||
args: { | |||
'service': frm.doc.service | |||
}, | |||
callback: function(r) { | |||
$(frm.fields_dict.custom_settings.wrapper).empty(); | |||
if (r.message.js){ | |||
frm.clear_custom_buttons(); | |||
frappe.require(r.message.js, function(){ | |||
service_name = frm.doc.service.toLowerCase().replace(/ /g, "_"); | |||
frappe.integration_service[service_name].load(frm); | |||
$(frm.fields_dict.scheduler_events_html.wrapper).empty(); | |||
if (frappe.integration_service[service_name].scheduler_job_helper) { | |||
frm.scheduler_helper = frappe.integration_service[service_name].scheduler_job_helper(); | |||
frm.events.render_scheduler_jobs(frm); | |||
} | |||
}) | |||
} | |||
frm.events.load_parameters(frm); | |||
} | |||
}) | |||
}, | |||
load_parameters: function(frm) { | |||
var form = frm; | |||
frappe.call({ | |||
method: 'frappe.integration_broker.doctype.integration_service.integration_service.get_service_parameters', | |||
args: { | |||
'service': frm.doc.service | |||
}, | |||
callback: function(r) { | |||
frm.fields = r.message.parameters; | |||
frm.scheduler_jobs = r.message.scheduled_jobs; | |||
frm.events.show_properties(frm); | |||
} | |||
setup_custom_buttons: function(frm) { | |||
frm.add_custom_button(__("{0} Settings", [frm.doc.service]), function(){ | |||
frappe.set_route("List", frm.doc.service + " Settings"); | |||
}); | |||
}, | |||
edit_settings: function(frm) { | |||
frm.events.setup_dialog(frm); | |||
}, | |||
setup_dialog: function(frm){ | |||
var d = new frappe.ui.Dialog({ | |||
title:__('Custom Settings'), | |||
fields: frm.fields | |||
frm.add_custom_button(__("Show Log"), function(){ | |||
frappe.route_options = {"integration_request_service": frm.doc.service}; | |||
frappe.set_route("List", "Integration Request"); | |||
}); | |||
// set_value | |||
if(frm.doc.custom_settings_json){ | |||
d.set_values(JSON.parse(frm.doc.custom_settings_json)); | |||
} | |||
d.set_primary_action(__("Set"), function() { | |||
var btn = this; | |||
var v = d.get_values(); | |||
if(!v) return; | |||
frm.set_value("custom_settings_json", JSON.stringify(v)); | |||
frm.refresh_field("custom_settings_json"); | |||
d.hide(); | |||
frm.events.show_properties(frm); | |||
}) | |||
d.show(); | |||
}, | |||
show_properties:function(frm){ | |||
var frm = frm; | |||
var table_wrapper = frm.fields_dict.custom_settings.wrapper; | |||
frm.settings = frm.doc.custom_settings_json ? JSON.parse(frm.doc.custom_settings_json) : {}; | |||
setup_service_details: function(frm) { | |||
var service_name = frm.doc.service.toLowerCase().replace(/ /g, "_"); | |||
var service_handelr = service_name + "_settings"; | |||
service_handelr = new frappe.integration_service[service_handelr](); | |||
service_handelr.get_service_info(frm); | |||
$(table_wrapper).empty(); | |||
$(table_wrapper).append('\ | |||
<table class="table table-bordered" style="cursor: pointer;">\ | |||
<thead>\ | |||
<tr>\ | |||
<th class="text-muted"> Parameter </th>\ | |||
<th class="text-muted"> Value </th>\ | |||
</tr>\ | |||
</thead> \ | |||
<tbody></tbody> \ | |||
</table>') | |||
frm.fields.forEach(function(d){ | |||
var df = d; | |||
$row = $("<tr>").appendTo($(table_wrapper).find("tbody")); | |||
$("<td>").appendTo($row).html(__(d.label)).css("font-size", "12px"); | |||
pwd_length = frm.settings[d.fieldname] ? frm.settings[d.fieldname].length : 0 | |||
value = (d.fieldtype == "Password") ? "*".repeat(pwd_length) : frm.settings[d.fieldname]; | |||
$("<td>").appendTo($row).html(value).css("font-size", "12px"); | |||
}); | |||
var scheduler_job_info = service_handelr.get_scheduler_job_info(); | |||
frm.events.render_scheduler_jobs(frm, scheduler_job_info); | |||
$(table_wrapper).find(".table-bordered").click(function(){ | |||
frm.events.setup_dialog(frm); | |||
}) | |||
}, | |||
render_scheduler_jobs: function(frm) { | |||
render_scheduler_jobs: function(frm, scheduler_job_info) { | |||
var schduler_job_view = frm.fields_dict.scheduler_events_html.wrapper; | |||
$(schduler_job_view).empty(); | |||
$(schduler_job_view).append('\ | |||
<table class="table table-bordered">\ | |||
@@ -137,8 +61,8 @@ frappe.ui.form.on('Integration Service', { | |||
</thead> \ | |||
<tbody></tbody> \ | |||
</table>') | |||
$.each(frm.scheduler_helper, function(evnt, help){ | |||
$.each(scheduler_job_info, function(evnt, help){ | |||
$row = $("<tr>").appendTo($(schduler_job_view).find("tbody")); | |||
$("<td>").appendTo($row).html(evnt).css("font-size", "12px"); | |||
$("<td>").appendTo($row).html(help).css("font-size", "12px"); | |||
@@ -70,34 +70,8 @@ | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"fieldname": "use_test_account", | |||
"fieldtype": "Check", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_list_view": 0, | |||
"label": "Use Test Account", | |||
"length": 0, | |||
"no_copy": 0, | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"read_only": 0, | |||
"report_hide": 0, | |||
"reqd": 0, | |||
"search_index": 0, | |||
"set_only_once": 0, | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"fieldname": "column_break_4", | |||
"fieldtype": "Column Break", | |||
"fieldname": "section_break_3", | |||
"fieldtype": "Section Break", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
@@ -143,109 +117,6 @@ | |||
"set_only_once": 0, | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"fieldname": "section_break_4", | |||
"fieldtype": "Section Break", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_list_view": 0, | |||
"length": 0, | |||
"no_copy": 0, | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"read_only": 0, | |||
"report_hide": 0, | |||
"reqd": 0, | |||
"search_index": 0, | |||
"set_only_once": 0, | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"fieldname": "custom_settings", | |||
"fieldtype": "HTML", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_list_view": 0, | |||
"label": "", | |||
"length": 0, | |||
"no_copy": 0, | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"read_only": 1, | |||
"report_hide": 0, | |||
"reqd": 0, | |||
"search_index": 0, | |||
"set_only_once": 0, | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"fieldname": "edit_settings", | |||
"fieldtype": "Button", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_list_view": 0, | |||
"label": "Edit Settings", | |||
"length": 0, | |||
"no_copy": 0, | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"read_only": 0, | |||
"report_hide": 0, | |||
"reqd": 0, | |||
"search_index": 0, | |||
"set_only_once": 0, | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"fieldname": "custom_settings_json", | |||
"fieldtype": "Code", | |||
"hidden": 1, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_list_view": 0, | |||
"label": "", | |||
"length": 0, | |||
"no_copy": 0, | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"read_only": 1, | |||
"report_hide": 0, | |||
"reqd": 0, | |||
"search_index": 0, | |||
"set_only_once": 0, | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
@@ -308,7 +179,7 @@ | |||
"issingle": 0, | |||
"istable": 0, | |||
"max_attachments": 0, | |||
"modified": "2016-09-24 05:48:04.652766", | |||
"modified": "2016-10-06 06:14:48.271314", | |||
"modified_by": "Administrator", | |||
"module": "Integration Broker", | |||
"name": "Integration Service", | |||
@@ -325,6 +196,7 @@ | |||
"export": 1, | |||
"if_owner": 0, | |||
"import": 0, | |||
"is_custom": 0, | |||
"permlevel": 0, | |||
"print": 1, | |||
"read": 1, | |||
@@ -13,35 +13,16 @@ from frappe.utils import get_request_session | |||
class IntegrationService(Document): | |||
def on_update(self): | |||
if self.enabled: | |||
self.enable_service() | |||
self.install_fixtures() | |||
def get_controller(self): | |||
if not getattr(self, '_controller', None): | |||
self._controller = get_integration_controller(self.service, setup=False) | |||
return self._controller | |||
def get_parameters(self): | |||
parameters = {} | |||
if self.custom_settings_json: | |||
parameters = json.loads(self.custom_settings_json) | |||
return parameters | |||
if not self.flags.ignore_mandatory: | |||
self.enable_service() | |||
self.install_fixtures() | |||
def install_fixtures(self): | |||
pass | |||
def enable_service(self): | |||
if not self.flags.ignore_mandatory: | |||
self.get_controller().enable(self.get_parameters(), self.use_test_account) | |||
def setup_events_and_parameters(self): | |||
self.parameters = [] | |||
for d in self.get_controller().parameters_template: | |||
self.parameters.append({'label': d.label, "value": d.value}) | |||
self.events = [] | |||
for d in self.get_controller()._events: | |||
self.parameters.append({'event': d.event, 'enabled': d.enabled}) | |||
service_doc = "{0} Settings".format(self.service) | |||
frappe.get_doc(service_doc).enable() | |||
#rest request handler | |||
def get_request(self, url, auth=None, data=None): | |||
@@ -99,46 +80,12 @@ class IntegrationService(Document): | |||
return integration_request | |||
@frappe.whitelist() | |||
def get_service_parameters(service): | |||
controller = get_integration_controller(service, setup=False) | |||
return { | |||
'parameters': controller.parameters_template, | |||
} | |||
@frappe.whitelist() | |||
def get_js_resouce(service): | |||
controller = get_integration_controller(service, setup=False) | |||
return { | |||
"js": getattr(controller, "js", "") | |||
} | |||
def get_integration_controller(service_name, setup=True): | |||
def get_integration_controller(service_name): | |||
'''Returns integration controller module from app_name.integrations.{service}''' | |||
def load_from_app(app, service_name): | |||
try: | |||
controller_module = frappe.get_module("{app}.integrations.{service}" | |||
.format(app=app, service=service_name.strip().lower().replace(' ','_'))) | |||
controller = controller_module.Controller(setup=setup) | |||
# make default properites and frappe._dictify | |||
for key in ('events', 'parameters_template'): | |||
tmp = [] | |||
for d in getattr(controller, key, []): | |||
tmp.append(frappe._dict(d)) | |||
setattr(controller, key, tmp) | |||
return controller | |||
except ImportError: | |||
pass | |||
for app in frappe.get_installed_apps(): | |||
controller = load_from_app(app, service_name) | |||
if controller: | |||
return controller | |||
frappe.throw(_("Module {service} not found".format(service=service_name))) | |||
try: | |||
return frappe.get_doc("{0} Settings".format(service_name)) | |||
except Exception: | |||
frappe.throw(_("Module {service} not found".format(service=service_name))) | |||
@frappe.whitelist() | |||
def get_integration_services(): | |||
@@ -150,11 +97,11 @@ def get_integration_services(): | |||
def trigger_integration_service_events(): | |||
for service in frappe.get_all("Integration Service", filters={"enabled": 1}, fields=["name"]): | |||
controller = get_integration_controller(service.name, setup=False) | |||
controller = get_integration_controller(service.name) | |||
if hasattr(controller, "scheduled_jobs"): | |||
for job in controller.scheduled_jobs: | |||
for event, handlers in job.items(): | |||
for handler in handlers: | |||
if handler not in get_jobs(): | |||
enqueue(handler, queue='short', event=event) | |||
enqueue(handler, queue='short', event=event) |
@@ -0,0 +1,64 @@ | |||
// Copyright (c) 2016, Frappe Technologies and contributors | |||
// For license information, please see license.txt | |||
frappe.provide("frappe.integration_service") | |||
frappe.ui.form.on('Dropbox Settings', { | |||
refresh: function(frm) { | |||
frm.clear_custom_buttons(); | |||
frm.events.take_backup(frm); | |||
}, | |||
allow_dropbox_access: function(frm) { | |||
if (frm.doc.app_access_key && frm.doc.app_secret_key) { | |||
frappe.call({ | |||
method: "frappe.integrations.doctype.dropbox_settings.dropbox_settings.get_dropbox_authorize_url", | |||
freeze: true, | |||
callback: function(r) { | |||
if(!r.exc) { | |||
frm.save(); | |||
window.open(r.message.url); | |||
} | |||
} | |||
}) | |||
} | |||
else { | |||
frappe.msgprint(__("Please enter values for App Access Key and App Secret Key")) | |||
} | |||
}, | |||
take_backup: function(frm) { | |||
if (frm.doc.app_access_key && frm.doc.app_secret_key && frm.doc.dropbox_access_key && frm.doc.dropbox_access_secret) { | |||
frm.add_custom_button(__("Take Backup Now"), function(frm){ | |||
frappe.call({ | |||
method: "frappe.integrations.dropbox_integration.take_backup", | |||
freeze: true | |||
}) | |||
}).addClass("btn-primary") | |||
} | |||
} | |||
}); | |||
frappe.integration_service.dropbox_settings = Class.extend({ | |||
init: function(frm) { | |||
}, | |||
get_scheduler_job_info: function() { | |||
return { | |||
"Daily": "Take backup of database and files to dropbox on daily basis", | |||
"Weekly": "Take backup of database and files to dropbox on weekly basis" | |||
} | |||
}, | |||
get_service_info: function(frm) { | |||
frappe.call({ | |||
method: "frappe.integrations.doctype.dropbox_settings.dropbox_settings.get_service_details", | |||
callback: function(r){ | |||
var integration_service_help = frm.fields_dict.integration_service_help.wrapper; | |||
$(integration_service_help).empty(); | |||
$(integration_service_help).append(r.message); | |||
} | |||
}) | |||
} | |||
}) |
@@ -0,0 +1,241 @@ | |||
{ | |||
"allow_copy": 0, | |||
"allow_import": 0, | |||
"allow_rename": 0, | |||
"beta": 0, | |||
"creation": "2016-09-21 10:12:57.399174", | |||
"custom": 0, | |||
"docstatus": 0, | |||
"doctype": "DocType", | |||
"document_type": "System", | |||
"editable_grid": 1, | |||
"fields": [ | |||
{ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"fieldname": "send_notifications_to", | |||
"fieldtype": "Data", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_list_view": 0, | |||
"label": "Send Notifications To", | |||
"length": 0, | |||
"no_copy": 0, | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"read_only": 0, | |||
"report_hide": 0, | |||
"reqd": 1, | |||
"search_index": 0, | |||
"set_only_once": 0, | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"fieldname": "backup_frequency", | |||
"fieldtype": "Select", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_list_view": 0, | |||
"label": "Backup Frequency", | |||
"length": 0, | |||
"no_copy": 0, | |||
"options": "\nDaily\nWeekly", | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"read_only": 0, | |||
"report_hide": 0, | |||
"reqd": 1, | |||
"search_index": 0, | |||
"set_only_once": 0, | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"fieldname": "app_access_key", | |||
"fieldtype": "Data", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_list_view": 0, | |||
"label": "App Access Key", | |||
"length": 0, | |||
"no_copy": 0, | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"read_only": 0, | |||
"report_hide": 0, | |||
"reqd": 1, | |||
"search_index": 0, | |||
"set_only_once": 0, | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"fieldname": "app_secret_key", | |||
"fieldtype": "Password", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_list_view": 0, | |||
"label": "App Secret Key", | |||
"length": 0, | |||
"no_copy": 0, | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"read_only": 0, | |||
"report_hide": 0, | |||
"reqd": 1, | |||
"search_index": 0, | |||
"set_only_once": 0, | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"fieldname": "allow_dropbox_access", | |||
"fieldtype": "Button", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_list_view": 0, | |||
"label": "Allow Dropbox Access", | |||
"length": 0, | |||
"no_copy": 0, | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"read_only": 0, | |||
"report_hide": 0, | |||
"reqd": 0, | |||
"search_index": 0, | |||
"set_only_once": 0, | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"fieldname": "dropbox_access_key", | |||
"fieldtype": "Password", | |||
"hidden": 1, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_list_view": 0, | |||
"label": "Dropbox Access Key", | |||
"length": 0, | |||
"no_copy": 0, | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"read_only": 1, | |||
"report_hide": 0, | |||
"reqd": 0, | |||
"search_index": 0, | |||
"set_only_once": 0, | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"fieldname": "dropbox_access_secret", | |||
"fieldtype": "Password", | |||
"hidden": 1, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_list_view": 0, | |||
"label": "Dropbox Access Secret", | |||
"length": 0, | |||
"no_copy": 0, | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"read_only": 1, | |||
"report_hide": 0, | |||
"reqd": 0, | |||
"search_index": 0, | |||
"set_only_once": 0, | |||
"unique": 0 | |||
} | |||
], | |||
"hide_heading": 0, | |||
"hide_toolbar": 0, | |||
"idx": 0, | |||
"image_view": 0, | |||
"in_create": 1, | |||
"in_dialog": 0, | |||
"is_submittable": 0, | |||
"issingle": 1, | |||
"istable": 0, | |||
"max_attachments": 0, | |||
"modified": "2016-09-22 03:55:40.716643", | |||
"modified_by": "Administrator", | |||
"module": "Integrations", | |||
"name": "Dropbox Settings", | |||
"name_case": "", | |||
"owner": "Administrator", | |||
"permissions": [ | |||
{ | |||
"amend": 0, | |||
"apply_user_permissions": 0, | |||
"cancel": 0, | |||
"create": 1, | |||
"delete": 1, | |||
"email": 1, | |||
"export": 1, | |||
"if_owner": 0, | |||
"import": 0, | |||
"permlevel": 0, | |||
"print": 1, | |||
"read": 1, | |||
"report": 0, | |||
"role": "System Manager", | |||
"set_user_permissions": 0, | |||
"share": 1, | |||
"submit": 0, | |||
"write": 1 | |||
} | |||
], | |||
"quick_entry": 0, | |||
"read_only": 1, | |||
"read_only_onload": 0, | |||
"sort_field": "modified", | |||
"sort_order": "DESC", | |||
"track_seen": 0 | |||
} |
@@ -1,58 +1,20 @@ | |||
# -*- coding: utf-8 -*- | |||
# Copyright (c) 2015, Frappe Technologies and contributors | |||
# For license information, please see license.txt | |||
from __future__ import unicode_literals | |||
import frappe | |||
import os | |||
from frappe import _ | |||
from frappe.integration_broker.integration_controller import IntegrationController | |||
from frappe.utils import (cint, split_emails, get_request_site_address, cstr, | |||
get_files_path, get_backups_path, encode) | |||
import os, json | |||
from frappe.utils.backups import new_backup | |||
from frappe.utils.background_jobs import enqueue | |||
from frappe.utils import (cint, split_emails, get_request_site_address, cstr, | |||
get_files_path, get_backups_path, encode) | |||
from frappe.integration_broker.doctype.integration_service.integration_service import IntegrationService | |||
ignore_list = [".DS_Store"] | |||
class Controller(IntegrationController): | |||
service_name = 'Dropbox Integration' | |||
parameters_template = [ | |||
{ | |||
"label": "App Access Key", | |||
'fieldname': 'app_access_key', | |||
'reqd': 1, | |||
'default': '', | |||
'fieldtype': "Data" | |||
}, | |||
{ | |||
"label": "App Secret Key", | |||
'fieldname': 'app_secret_key', | |||
'reqd': 1, | |||
'default': '', | |||
'fieldtype': "Password" | |||
}, | |||
{ | |||
"label": "Dropbox Access Key", | |||
'fieldname': 'dropbox_access_key', | |||
'reqd': 1, | |||
'default': '****', | |||
'fieldtype': "Password" | |||
}, | |||
{ | |||
"label": "Dropbox Secret Key", | |||
'fieldname': 'dropbox_access_secret', | |||
'reqd': 1, | |||
'default': '****', | |||
'fieldtype': "Password" | |||
}, | |||
{ | |||
"label": "Backup Frequency", | |||
"fieldname": "backup_frequency", | |||
"options": "\nDaily\nWeekly", | |||
"default": "", | |||
"reqd": 1, | |||
"fieldtype":'Select' | |||
} | |||
] | |||
js = "assets/frappe/js/integrations/dropbox_integration.js" | |||
# do also changes in dropbox_integration.js scheduler job helper | |||
class DropboxSettings(IntegrationService): | |||
scheduled_jobs = [ | |||
{ | |||
"daily_long": [ | |||
@@ -64,10 +26,17 @@ class Controller(IntegrationController): | |||
} | |||
] | |||
def enable(self, parameters, use_test_account=0): | |||
def validate(self): | |||
if not self.flags.ignore_mandatory: | |||
self.validate_dropbox_credentails() | |||
def on_update(self): | |||
pass | |||
def enable(self): | |||
""" enable service """ | |||
self.parameters = parameters | |||
self.validate_dropbox_credentails() | |||
if not self.flags.ignore_mandatory: | |||
self.validate_dropbox_credentails() | |||
def validate_dropbox_credentails(self): | |||
try: | |||
@@ -80,30 +49,71 @@ class Controller(IntegrationController): | |||
from dropbox import session | |||
except: | |||
raise Exception(_("Please install dropbox python module")) | |||
parameters = frappe._dict(self.parameters) | |||
if not (parameters["app_access_key"] or parameters["app_secret_key"]): | |||
if not (self.app_access_key or self.app_secret_key): | |||
raise Exception(_("Please set Dropbox access keys in your site config")) | |||
sess = session.DropboxSession(parameters["app_access_key"], parameters["app_secret_key"], "app_folder") | |||
sess = session.DropboxSession(self.app_access_key, | |||
self.get_password(fieldname="app_secret_key", raise_exception=False), "app_folder") | |||
return sess | |||
@frappe.whitelist() | |||
def get_service_details(): | |||
return """ | |||
<div> | |||
Steps to enable dropbox backup service: | |||
<ol> | |||
<li> Create a dropbox app then get App Key and App Secret, | |||
<a href="https://www.dropbox.com/developers/apps" target="_blank"> | |||
https://www.dropbox.com/developers/apps | |||
</a> | |||
</li> | |||
<br> | |||
<li> Setup credentials on Dropbox Settings doctype. | |||
Click on | |||
<button class="btn btn-default btn-xs disabled"> Dropbox Settings </button> | |||
top right corner | |||
</li> | |||
<br> | |||
<li> After settings up App key and App Secret, generate access token | |||
<button class="btn btn-default btn-xs disabled"> Allow Dropbox Access </button> | |||
</li> | |||
<br> | |||
<li> | |||
After saving settings, | |||
<label> | |||
<span class="input-area"> | |||
<input type="checkbox" class="input-with-feedback" checked disabled> | |||
</span> | |||
<span class="label-area small">Enable</span> | |||
</label> | |||
Dropbox Integration Service and Save a document. | |||
</li> | |||
</ol> | |||
<p> | |||
After enabling service, system will take backup of files and database on daily or weekly basis | |||
as per set on Dropbox Settings page and upload it to your dropbox. | |||
</p> | |||
</div> | |||
""" | |||
#get auth token | |||
@frappe.whitelist() | |||
def get_dropbox_authorize_url(): | |||
doc = frappe.get_doc("Integration Service", "Dropbox Integration") | |||
Controller.parameters = json.loads(doc.custom_settings_json) | |||
sess = Controller().get_dropbox_session() | |||
doc = frappe.get_doc("Dropbox Settings") | |||
sess = doc.get_dropbox_session() | |||
request_token = sess.obtain_request_token() | |||
setup_parameter({ | |||
doc.update({ | |||
"dropbox_access_key": request_token.key, | |||
"dropbox_access_secret": request_token.secret | |||
}, doc) | |||
}) | |||
doc.save(ignore_permissions=False) | |||
return_address = get_request_site_address(True) \ | |||
+ "?cmd=frappe.integrations.dropbox_integration.dropbox_callback" | |||
+ "?cmd=frappe.integrations.doctype.dropbox_settings.dropbox_settings.dropbox_callback" | |||
url = sess.build_authorize_url(request_token, return_address) | |||
@@ -113,34 +123,20 @@ def get_dropbox_authorize_url(): | |||
"dropbox_access_secret": request_token.secret | |||
} | |||
def setup_parameter(request_token, doc): | |||
parameters = Controller().parameters | |||
for key in ["dropbox_access_key", "dropbox_access_secret"]: | |||
for parameter in Controller().parameters: | |||
if key == parameter: | |||
parameters[key] = request_token[key] | |||
doc.custom_settings_json = json.dumps(parameters) | |||
doc.save(ignore_permissions=True) | |||
frappe.db.commit() | |||
@frappe.whitelist(allow_guest=True) | |||
def dropbox_callback(oauth_token=None, not_approved=False): | |||
doc = frappe.get_doc("Integration Service", "Dropbox Integration") | |||
Controller.parameters = json.loads(doc.custom_settings_json) | |||
doc = frappe.get_doc("Dropbox Settings") | |||
parameters = Controller().get_parameters() | |||
if not not_approved: | |||
if parameters["dropbox_access_key"]==oauth_token: | |||
sess = Controller().get_dropbox_session() | |||
sess.set_request_token(parameters["dropbox_access_key"], parameters["dropbox_access_secret"]) | |||
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() | |||
setup_parameter({ | |||
"dropbox_access_key": access_token.key, | |||
"dropbox_access_secret": access_token.secret | |||
}, doc) | |||
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: | |||
@@ -157,7 +153,7 @@ def dropbox_callback(oauth_token=None, not_approved=False): | |||
@frappe.whitelist() | |||
def take_backup(): | |||
"Enqueue longjob for taking backup to dropbox" | |||
enqueue("frappe.integrations.dropbox_integration.take_backup_to_dropbox", queue='long') | |||
enqueue("frappe.integrations.doctype.dropbox_settings.dropbox_settings.take_backup_to_dropbox", queue='long') | |||
frappe.msgprint(_("Queued for backup. It may take a few minutes to an hour.")) | |||
def take_backups_daily(): | |||
@@ -167,16 +163,13 @@ def take_backups_weekly(): | |||
take_backups_if("Weekly") | |||
def take_backups_if(freq): | |||
custom_settings_json = frappe.db.get_value("Dropbox Backup", None, "custom_settings_json") | |||
if custom_settings_json: | |||
custom_settings_json = json.loads(custom_settings_json) | |||
if custom_settings_json["backup_frequency"] == freq: | |||
take_backup_to_dropbox() | |||
if frappe.db.get_value("Dropbox Settings", None, "backup_frequency") == freq: | |||
take_backup_to_dropbox() | |||
def take_backup_to_dropbox(): | |||
did_not_upload, error_log = [], [] | |||
try: | |||
if cint(frappe.db.get_value("Integration Service", "Dropbox Integration", "enabled")): | |||
if cint(frappe.db.get_value("Integration Service", "Dropbox", "enabled")): | |||
did_not_upload, error_log = backup_to_dropbox() | |||
if did_not_upload: raise Exception | |||
@@ -235,13 +228,11 @@ def backup_to_dropbox(): | |||
def get_dropbox_client(previous_dropbox_client=None): | |||
from dropbox import client | |||
doc = frappe.get_doc("Integration Service", "Dropbox Integration") | |||
Controller.parameters = json.loads(doc.custom_settings_json) | |||
sess = Controller().get_dropbox_session() | |||
doc = frappe.get_doc("Dropbox Settings") | |||
sess = doc.get_dropbox_session() | |||
parameters = Controller().get_parameters() | |||
sess.set_token(parameters["dropbox_access_key"], parameters["dropbox_access_secret"]) | |||
sess.set_token(doc.get_password(fieldname="dropbox_access_key", raise_exception=False), | |||
doc.get_password(fieldname="dropbox_access_secret", raise_exception=False)) | |||
dropbox_client = client.DropboxClient(sess) | |||
@@ -0,0 +1,12 @@ | |||
# -*- coding: utf-8 -*- | |||
# Copyright (c) 2015, Frappe Technologies and Contributors | |||
# See license.txt | |||
from __future__ import unicode_literals | |||
import frappe | |||
import unittest | |||
# test_records = frappe.get_test_records('Dropbox Settings') | |||
class TestDropboxSettings(unittest.TestCase): | |||
pass |
@@ -0,0 +1,31 @@ | |||
// Copyright (c) 2016, Frappe Technologies and contributors | |||
// For license information, please see license.txt | |||
frappe.provide("frappe.integration_service") | |||
frappe.ui.form.on('LDAP Settings', { | |||
refresh: function(frm) { | |||
} | |||
}); | |||
frappe.integration_service.ldap_settings = Class.extend({ | |||
init: function(frm) { | |||
}, | |||
get_scheduler_job_info: function() { | |||
return {} | |||
}, | |||
get_service_info: function(frm) { | |||
frappe.call({ | |||
method: "frappe.integrations.doctype.ldap_settings.ldap_settings.get_service_details", | |||
callback: function(r){ | |||
var integration_service_help = frm.fields_dict.integration_service_help.wrapper; | |||
$(integration_service_help).empty(); | |||
$(integration_service_help).append(r.message); | |||
} | |||
}) | |||
} | |||
}) |
@@ -0,0 +1,162 @@ | |||
{ | |||
"allow_copy": 0, | |||
"allow_import": 0, | |||
"allow_rename": 0, | |||
"beta": 0, | |||
"creation": "2016-09-22 04:16:48.829658", | |||
"custom": 0, | |||
"docstatus": 0, | |||
"doctype": "DocType", | |||
"document_type": "System", | |||
"editable_grid": 1, | |||
"fields": [ | |||
{ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"fieldname": "ldap_server_url", | |||
"fieldtype": "Data", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_list_view": 0, | |||
"label": "LDAP Server Url", | |||
"length": 0, | |||
"no_copy": 0, | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"read_only": 0, | |||
"report_hide": 0, | |||
"reqd": 1, | |||
"search_index": 0, | |||
"set_only_once": 0, | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"fieldname": "organizational_unit", | |||
"fieldtype": "Data", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_list_view": 0, | |||
"label": "Organizational Unit", | |||
"length": 0, | |||
"no_copy": 0, | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"read_only": 0, | |||
"report_hide": 0, | |||
"reqd": 1, | |||
"search_index": 0, | |||
"set_only_once": 0, | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"fieldname": "base_dn", | |||
"fieldtype": "Data", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_list_view": 0, | |||
"label": "Base Distinguished Name (DN)", | |||
"length": 0, | |||
"no_copy": 0, | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"read_only": 0, | |||
"report_hide": 0, | |||
"reqd": 1, | |||
"search_index": 0, | |||
"set_only_once": 0, | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"fieldname": "password", | |||
"fieldtype": "Password", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_list_view": 0, | |||
"label": "Password for Base DN", | |||
"length": 0, | |||
"no_copy": 0, | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"read_only": 0, | |||
"report_hide": 0, | |||
"reqd": 1, | |||
"search_index": 0, | |||
"set_only_once": 0, | |||
"unique": 0 | |||
} | |||
], | |||
"hide_heading": 0, | |||
"hide_toolbar": 0, | |||
"idx": 0, | |||
"image_view": 0, | |||
"in_create": 1, | |||
"in_dialog": 0, | |||
"is_submittable": 0, | |||
"issingle": 1, | |||
"istable": 0, | |||
"max_attachments": 0, | |||
"modified": "2016-09-22 04:31:42.998441", | |||
"modified_by": "Administrator", | |||
"module": "Integrations", | |||
"name": "LDAP Settings", | |||
"name_case": "", | |||
"owner": "Administrator", | |||
"permissions": [ | |||
{ | |||
"amend": 0, | |||
"apply_user_permissions": 0, | |||
"cancel": 0, | |||
"create": 1, | |||
"delete": 1, | |||
"email": 1, | |||
"export": 1, | |||
"if_owner": 0, | |||
"import": 0, | |||
"permlevel": 0, | |||
"print": 1, | |||
"read": 1, | |||
"report": 0, | |||
"role": "System Manager", | |||
"set_user_permissions": 0, | |||
"share": 1, | |||
"submit": 0, | |||
"write": 1 | |||
} | |||
], | |||
"quick_entry": 0, | |||
"read_only": 1, | |||
"read_only_onload": 0, | |||
"sort_field": "modified", | |||
"sort_order": "DESC", | |||
"track_seen": 0 | |||
} |
@@ -0,0 +1,168 @@ | |||
# -*- coding: utf-8 -*- | |||
# Copyright (c) 2015, Frappe Technologies and contributors | |||
# For license information, please see license.txt | |||
from __future__ import unicode_literals | |||
import frappe | |||
from frappe import _ | |||
from frappe.utils import cstr, cint | |||
from frappe.integration_broker.doctype.integration_service.integration_service import IntegrationService | |||
class LDAPSettings(IntegrationService): | |||
def on_update(self): | |||
pass | |||
def validate(self): | |||
if not self.flags.ignore_mandatory: | |||
self.validate_ldap_credentails() | |||
def enable(self): | |||
if not self.flags.ignore_mandatory: | |||
self.validate_ldap_credentails() | |||
def validate_ldap_credentails(self): | |||
try: | |||
import ldap | |||
conn = ldap.initialize(self.ldap_server_url) | |||
conn.simple_bind_s(self.base_dn, self.get_password(raise_exception=False)) | |||
raise ImportError | |||
except ImportError: | |||
msg = """ | |||
<div> | |||
Seems ldap is not installed on system.<br> | |||
Guidelines to install ldap dependancies and python package, | |||
<a href="https://discuss.erpnext.com/t/frappe-v-7-1-beta-ldap-dependancies/15841" target="_blank">Click here</a>, | |||
</div> | |||
""" | |||
frappe.throw(msg, title="LDAP Not Installed") | |||
except ldap.LDAPError: | |||
conn.unbind_s() | |||
frappe.throw("Incorrect UserId or Password") | |||
@frappe.whitelist() | |||
def get_service_details(): | |||
return """ | |||
<div> | |||
<p> Steps to configure Service | |||
<ol> | |||
<li> Setup credentials on LDAP settings doctype | |||
Click on | |||
<button class="btn btn-default btn-xs disabled"> LDAP Settings </button> | |||
top right corner | |||
<br> | |||
To setup LDAP you need, | |||
<ul> | |||
<li> Server URL & Port : ldap://ldap.forumsys.com:389</li> | |||
<li> Base Distinguished Name : cn=read-only-admin,dc=example,dc=com</li> | |||
<li> Organisational Unit : ou=mathematicians,dc=example,dc=com</li> | |||
<li> Password : Base DN password </li> | |||
</ul> | |||
</li> | |||
<br> | |||
<li> | |||
After saving settings, | |||
<label> | |||
<span class="input-area"> | |||
<input type="checkbox" class="input-with-feedback" checked disabled> | |||
</span> | |||
<span class="label-area small">Enable</span> | |||
</label> | |||
LDAP Integration Service and Save a document. | |||
</li> | |||
</ol> | |||
</div> | |||
""" | |||
def get_ldap_settings(): | |||
try: | |||
settings = frappe.get_doc("LDAP Settings") | |||
settings.update({ | |||
"enabled": cint(frappe.db.get_value("Integration Service", "LDAP", "enabled")), | |||
"method": "frappe.integrations.doctype.ldap_settings.ldap_settings.login" | |||
}) | |||
return settings | |||
except Exception: | |||
# this will return blank settings | |||
return frappe._dict() | |||
@frappe.whitelist(allow_guest=True) | |||
def login(): | |||
#### LDAP LOGIN LOGIC ##### | |||
args = frappe.form_dict | |||
user = authenticate_ldap_user(args.usr, args.pwd) | |||
frappe.local.login_manager.user = user.name | |||
frappe.local.login_manager.post_login() | |||
# because of a GET request! | |||
frappe.db.commit() | |||
def authenticate_ldap_user(user=None, password=None): | |||
dn = None | |||
params = {} | |||
settings = get_ldap_settings() | |||
try: | |||
import ldap | |||
except: | |||
msg = """ | |||
<div> | |||
{{_("Seems ldap is not installed on system")}}.<br> | |||
<a href"https://discuss.erpnext.com/t/frappe-v-7-1-beta-ldap-dependancies/15841">Click here</a>, | |||
{{_("Guidelines to install ldap dependancies and python")}} | |||
</div> | |||
""" | |||
frappe.throw(msg, title="LDAP Not Installed") | |||
conn = ldap.initialize(settings.ldap_server_url) | |||
try: | |||
# simple_bind_s is synchronous binding to server, it takes two param DN and password | |||
conn.simple_bind_s(settings.base_dn, settings.get_password(raise_exception=False)) | |||
#search for surnames beginning with a | |||
#available options for how deep a search you want. | |||
#LDAP_SCOPE_BASE, LDAP_SCOPE_ONELEVEL,LDAP_SCOPE_SUBTREE, | |||
result = conn.search_s(settings.organizational_unit, ldap.SCOPE_SUBTREE, | |||
"uid=*{0}".format(user)) | |||
print result | |||
for dn, r in result: | |||
dn = cstr(dn) | |||
params["email"] = cstr(r['mail'][0]) | |||
params["username"] = cstr(r['uid'][0]) | |||
params["first_name"] = cstr(r['cn'][0]) | |||
if dn: | |||
conn.simple_bind_s(dn, password) | |||
return create_user(params) | |||
else: | |||
frappe.throw(_("Not a valid LDAP user")) | |||
except ldap.LDAPError: | |||
conn.unbind_s() | |||
frappe.throw(_("Incorrect UserId or Password")) | |||
def create_user(params): | |||
if frappe.db.exists("User", params["email"]): | |||
return frappe.get_doc("User", params["email"]) | |||
else: | |||
params.update({ | |||
"doctype": "User", | |||
"send_welcome_email": 0, | |||
"language": "", | |||
"user_type": "System User", | |||
"user_roles": [{ | |||
"role": _("Blogger") | |||
}] | |||
}) | |||
user = frappe.get_doc(params).insert(ignore_permissions=True) | |||
frappe.db.commit() | |||
return user |
@@ -0,0 +1,31 @@ | |||
// Copyright (c) 2016, Frappe Technologies and contributors | |||
// For license information, please see license.txt | |||
frappe.provide("frappe.integration_service") | |||
frappe.ui.form.on('PayPal Settings', { | |||
refresh: function(frm) { | |||
} | |||
}); | |||
frappe.integration_service.paypal_settings = Class.extend({ | |||
init: function(frm) { | |||
}, | |||
get_scheduler_job_info: function() { | |||
return {} | |||
}, | |||
get_service_info: function(frm) { | |||
frappe.call({ | |||
method: "frappe.integrations.doctype.paypal_settings.paypal_settings.get_service_details", | |||
callback: function(r){ | |||
var integration_service_help = frm.fields_dict.integration_service_help.wrapper; | |||
$(integration_service_help).empty(); | |||
$(integration_service_help).append(r.message); | |||
} | |||
}) | |||
} | |||
}) |
@@ -0,0 +1,190 @@ | |||
{ | |||
"allow_copy": 0, | |||
"allow_import": 0, | |||
"allow_rename": 0, | |||
"beta": 0, | |||
"creation": "2016-09-21 08:03:01.009852", | |||
"custom": 0, | |||
"docstatus": 0, | |||
"doctype": "DocType", | |||
"document_type": "System", | |||
"editable_grid": 1, | |||
"fields": [ | |||
{ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"fieldname": "api_username", | |||
"fieldtype": "Data", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_list_view": 0, | |||
"label": "API Username", | |||
"length": 0, | |||
"no_copy": 0, | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"read_only": 0, | |||
"report_hide": 0, | |||
"reqd": 1, | |||
"search_index": 0, | |||
"set_only_once": 0, | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"fieldname": "api_password", | |||
"fieldtype": "Password", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_list_view": 0, | |||
"label": "API Password", | |||
"length": 0, | |||
"no_copy": 0, | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"read_only": 0, | |||
"report_hide": 0, | |||
"reqd": 1, | |||
"search_index": 0, | |||
"set_only_once": 0, | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"fieldname": "signature", | |||
"fieldtype": "Data", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_list_view": 0, | |||
"label": "Signature", | |||
"length": 0, | |||
"no_copy": 0, | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"read_only": 0, | |||
"report_hide": 0, | |||
"reqd": 1, | |||
"search_index": 0, | |||
"set_only_once": 0, | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"description": "Check this if you are testing your payment using the Sandbox API", | |||
"fieldname": "paypal_sandbox", | |||
"fieldtype": "Check", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_list_view": 0, | |||
"label": "Use Sandbox", | |||
"length": 0, | |||
"no_copy": 0, | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"read_only": 0, | |||
"report_hide": 0, | |||
"reqd": 0, | |||
"search_index": 0, | |||
"set_only_once": 0, | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"description": "Mention transaction completion page URL", | |||
"fieldname": "redirect_to", | |||
"fieldtype": "Data", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_list_view": 0, | |||
"label": "Redirect To", | |||
"length": 0, | |||
"no_copy": 0, | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"read_only": 0, | |||
"report_hide": 0, | |||
"reqd": 0, | |||
"search_index": 0, | |||
"set_only_once": 0, | |||
"unique": 0 | |||
} | |||
], | |||
"hide_heading": 0, | |||
"hide_toolbar": 0, | |||
"idx": 0, | |||
"image_view": 0, | |||
"in_create": 1, | |||
"in_dialog": 0, | |||
"is_submittable": 0, | |||
"issingle": 1, | |||
"istable": 0, | |||
"max_attachments": 0, | |||
"modified": "2016-09-26 02:00:45.145155", | |||
"modified_by": "Administrator", | |||
"module": "Integrations", | |||
"name": "PayPal Settings", | |||
"name_case": "", | |||
"owner": "Administrator", | |||
"permissions": [ | |||
{ | |||
"amend": 0, | |||
"apply_user_permissions": 0, | |||
"cancel": 0, | |||
"create": 1, | |||
"delete": 1, | |||
"email": 1, | |||
"export": 1, | |||
"if_owner": 0, | |||
"import": 0, | |||
"permlevel": 0, | |||
"print": 1, | |||
"read": 1, | |||
"report": 0, | |||
"role": "System Manager", | |||
"set_user_permissions": 0, | |||
"share": 1, | |||
"submit": 0, | |||
"write": 1 | |||
} | |||
], | |||
"quick_entry": 0, | |||
"read_only": 1, | |||
"read_only_onload": 0, | |||
"sort_field": "modified", | |||
"sort_order": "DESC", | |||
"track_seen": 0 | |||
} |
@@ -1,6 +1,15 @@ | |||
# -*- coding: utf-8 -*- | |||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors | |||
# License: GNU General Public License v3. See license.txt | |||
# Copyright (c) 2015, Frappe Technologies and contributors | |||
# For license information, please see license.txt | |||
from __future__ import unicode_literals | |||
import frappe | |||
import json | |||
from frappe import _ | |||
from frappe.utils import get_url, call_hook_method | |||
from urllib import urlencode | |||
from frappe.integration_broker.doctype.integration_service.integration_service import IntegrationService | |||
import urllib | |||
""" | |||
# Integrating PayPal | |||
@@ -11,7 +20,7 @@ Example: | |||
from frappe.integration_broker.doctype.integration_service.integration_service import get_integration_controller | |||
controller = get_integration_controller("PayPal", setup=False) | |||
controller = get_integration_controller("PayPal") | |||
controller().validate_transaction_currency(currency) | |||
### 2. Redirect for payment | |||
@@ -48,79 +57,49 @@ Example: | |||
payment_status - payment gateway will put payment status on callback. | |||
For paypal payment status parameter is one from: [Completed, Cancelled, Failed] | |||
""" | |||
from __future__ import unicode_literals | |||
import frappe | |||
import json | |||
from frappe import _ | |||
from urllib import urlencode | |||
from frappe.utils import get_url, call_hook_method | |||
from frappe.integration_broker.integration_controller import IntegrationController | |||
class Controller(IntegrationController): | |||
service_name = 'PayPal' | |||
parameters_template = [ | |||
{ | |||
"label": "API Username", | |||
'fieldname': 'api_username', | |||
'fieldtype': 'Data', | |||
'reqd': 1 | |||
}, | |||
{ | |||
"label": "API Password", | |||
'fieldname': 'api_password', | |||
'fieldtype': "Password", | |||
'reqd': 1 | |||
}, | |||
{ | |||
"label": "Signature", | |||
"fieldname": "signature", | |||
'fieldtype': "Data", | |||
"reqd": 1 | |||
} | |||
] | |||
More Details: | |||
<div class="small">For details on how to get your API credentials, follow this link: <a href="https://developer.paypal.com/docs/classic/api/apiCredentials/" target="_blank">https://developer.paypal.com/docs/classic/api/apiCredentials/</a></div> | |||
js = "assets/frappe/js/integrations/paypal.js" | |||
""" | |||
class PayPalSettings(IntegrationService): | |||
service_name = "PayPal" | |||
supported_currencies = ["AUD", "BRL", "CAD", "CZK", "DKK", "EUR", "HKD", "HUF", "ILS", "JPY", "MYR", "MXN", | |||
"TWD", "NZD", "NOK", "PHP", "PLN", "GBP", "RUB", "SGD", "SEK", "CHF", "THB", "TRY", "USD"] | |||
def enable(self, parameters, use_test_account=0): | |||
def validate(self): | |||
if not self.flags.ignore_mandatory: | |||
self.validate_paypal_credentails() | |||
def on_update(self): | |||
pass | |||
def enable(self): | |||
call_hook_method('payment_gateway_enabled', gateway=self.service_name) | |||
self.parameters = parameters | |||
self.validate_paypal_credentails(use_test_account) | |||
def get_settings(self): | |||
if not hasattr(self, "parameters"): | |||
parameters = frappe.db.get_value("Integration Service", self.service_name, | |||
["custom_settings_json"]) | |||
self.parameters = json.loads(parameters) | |||
if not self.flags.ignore_mandatory: | |||
self.validate_paypal_credentails() | |||
return frappe._dict(self.parameters) | |||
def validate_transaction_currency(self, currency): | |||
if currency not in self.supported_currencies: | |||
frappe.throw(_("Please select another payment method. {0} does not support transactions in currency '{1}'").format(self.service_name, currency)) | |||
def get_paypal_params_and_url(self, use_test_account=None): | |||
use_test_account = frappe.db.get_value("Integration Service", self.service_name, ["use_test_account"]) | |||
paypal_settings = frappe._dict(self.get_settings()) | |||
def get_paypal_params_and_url(self): | |||
params = { | |||
"USER": paypal_settings.api_username, | |||
"PWD": paypal_settings.api_password, | |||
"SIGNATURE": paypal_settings.signature, | |||
"USER": self.api_username, | |||
"PWD": self.get_password(fieldname="api_password", raise_exception=False), | |||
"SIGNATURE": self.signature, | |||
"VERSION": "98", | |||
"METHOD": "GetPalDetails" | |||
} | |||
api_url = "https://api-3t.sandbox.paypal.com/nvp" if use_test_account else "https://api-3t.paypal.com/nvp" | |||
api_url = "https://api-3t.sandbox.paypal.com/nvp" if self.paypal_sandbox else "https://api-3t.paypal.com/nvp" | |||
return params, api_url | |||
def validate_paypal_credentails(self, use_test_account): | |||
params, url = self.get_paypal_params_and_url(use_test_account) | |||
def validate_paypal_credentails(self): | |||
params, url = self.get_paypal_params_and_url() | |||
params = urlencode(params) | |||
try: | |||
@@ -131,12 +110,11 @@ class Controller(IntegrationController): | |||
except Exception: | |||
frappe.throw(_("Invalid payment gateway credentials")) | |||
def get_payment_url(self, **kwargs): | |||
use_test_account = frappe.db.get_value("Integration Service", self.service_name, ["use_test_account"]) | |||
response = self.execute_set_express_checkout(kwargs["amount"], kwargs["currency"]) | |||
if use_test_account: | |||
if self.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}" | |||
@@ -169,15 +147,53 @@ class Controller(IntegrationController): | |||
return response | |||
@frappe.whitelist() | |||
def get_service_details(): | |||
return """ | |||
<div> | |||
<p> Steps to configure Service | |||
<ol> | |||
<li> Get PayPal api credentials from link: | |||
<a href="https://developer.paypal.com/docs/classic/api/apiCredentials/" target="_blank"> | |||
https://developer.paypal.com/docs/classic/api/apiCredentials/ | |||
</a> | |||
</li> | |||
<br> | |||
<li> Setup credentials on PayPal settings doctype. | |||
Click on | |||
<button class="btn btn-default btn-xs disabled"> PayPal Settings </button> | |||
top right corner | |||
</li> | |||
<br> | |||
<li> | |||
After saving settings, | |||
<label> | |||
<span class="input-area"> | |||
<input type="checkbox" class="input-with-feedback" checked disabled> | |||
</span> | |||
<span class="label-area small">Enabled</span> | |||
</label> | |||
PayPal Integration Service and Save a document. | |||
</li> | |||
<br> | |||
<li> | |||
To view PayPal payment logs, | |||
<button class="btn btn-default btn-xs disabled"> Show Log </button> | |||
</li> | |||
</ol> | |||
</div> | |||
""" | |||
@frappe.whitelist(allow_guest=True, xss_safe=True) | |||
def get_express_checkout_details(token): | |||
params, url = Controller().get_paypal_params_and_url() | |||
doc = frappe.get_doc("PayPal Settings") | |||
params, url = doc.get_paypal_params_and_url() | |||
params.update({ | |||
"METHOD": "GetExpressCheckoutDetails", | |||
"TOKEN": token | |||
}) | |||
response = Controller().post_request(url, data=params) | |||
response = doc.post_request(url, data=params) | |||
if response.get("ACK")[0] != "Success": | |||
frappe.respond_as_web_page(_("Something went wrong"), | |||
@@ -200,10 +216,14 @@ def get_express_checkout_details(token): | |||
def confirm_payment(token): | |||
redirect = True | |||
status_changed_to, redirect_to = None, None | |||
doc = frappe.get_doc("PayPal Settings") | |||
integration_request = frappe.get_doc("Integration Request", token) | |||
data = json.loads(integration_request.data) | |||
params, url = Controller().get_paypal_params_and_url() | |||
redirect_to = data.get('redirect_to') or None | |||
redirect_message = data.get('redirect_message') or None | |||
params, url = doc.get_paypal_params_and_url() | |||
params.update({ | |||
"METHOD": "DoExpressCheckoutPayment", | |||
"PAYERID": data.get("payerid"), | |||
@@ -213,7 +233,7 @@ def confirm_payment(token): | |||
"PAYMENTREQUEST_0_CURRENCYCODE": data.get("currency").upper() | |||
}) | |||
response = Controller().post_request(url, data=params) | |||
response = doc.post_request(url, data=params) | |||
if response.get("ACK")[0] == "Success": | |||
update_integration_request_status(token, { | |||
@@ -222,21 +242,22 @@ def confirm_payment(token): | |||
}, "Completed") | |||
if data.get("reference_doctype") and data.get("reference_docname"): | |||
redirect_to = frappe.get_doc(data.get("reference_doctype"), data.get("reference_docname")).run_method("on_payment_authorized", "Completed") | |||
if not redirect_to: | |||
if data.get('redirect_to'): | |||
redirect_to = data.get('redirect_to') | |||
redirect_to = redirect_to or get_url("/integrations/payment-success") | |||
redirect_url = frappe.get_doc(data.get("reference_doctype"), data.get("reference_docname")).run_method("on_payment_authorized", "Completed") | |||
if not redirect_url: | |||
redirect_url = '/integrations/payment-success' | |||
else: | |||
redirect_to = get_url("/integrations/payment-failed") | |||
redirect_url = "/integrations/payment-failed" | |||
if redirect_to: | |||
redirect_url += '?' + urllib.urlencode({'redirect_to': redirect_to}) | |||
if redirect_message: | |||
redirect_url += '&' + urllib.urlencode({'redirect_message': redirect_message}) | |||
# this is done so that functions called via hooks can update flags.redirect_to | |||
if redirect: | |||
frappe.local.response["type"] = "redirect" | |||
frappe.local.response["location"] = redirect_to | |||
frappe.local.response["location"] = get_url(redirect_to) | |||
def update_integration_request_status(token, data, status, error=False): | |||
frappe.get_doc("Integration Request", token).update_status(data, status) | |||
@@ -244,7 +265,8 @@ def update_integration_request_status(token, data, status, error=False): | |||
@frappe.whitelist(allow_guest=True, xss_safe=True) | |||
def get_checkout_url(**kwargs): | |||
try: | |||
return Controller().get_payment_url(**kwargs) | |||
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."), |
@@ -0,0 +1,33 @@ | |||
// Copyright (c) 2016, Frappe Technologies and contributors | |||
// For license information, please see license.txt | |||
frappe.provide("frappe.integration_service") | |||
frappe.ui.form.on('Razorpay Settings', { | |||
refresh: function(frm) { | |||
} | |||
}); | |||
frappe.integration_service.razorpay_settings = Class.extend({ | |||
init: function(frm) { | |||
}, | |||
get_scheduler_job_info: function() { | |||
return { | |||
"Execute on every few minits of interval": " Captures all authorised payments" | |||
} | |||
}, | |||
get_service_info: function(frm) { | |||
frappe.call({ | |||
method: "frappe.integrations.doctype.razorpay_settings.razorpay_settings.get_service_details", | |||
callback: function(r){ | |||
var integration_service_help = frm.fields_dict.integration_service_help.wrapper; | |||
$(integration_service_help).empty(); | |||
$(integration_service_help).append(r.message); | |||
} | |||
}) | |||
} | |||
}) |
@@ -0,0 +1,137 @@ | |||
{ | |||
"allow_copy": 0, | |||
"allow_import": 0, | |||
"allow_rename": 0, | |||
"beta": 0, | |||
"creation": "2016-09-20 03:44:03.799402", | |||
"custom": 0, | |||
"docstatus": 0, | |||
"doctype": "DocType", | |||
"document_type": "System", | |||
"editable_grid": 1, | |||
"fields": [ | |||
{ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"fieldname": "api_key", | |||
"fieldtype": "Data", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_list_view": 0, | |||
"label": "API Key", | |||
"length": 0, | |||
"no_copy": 0, | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"read_only": 0, | |||
"report_hide": 0, | |||
"reqd": 1, | |||
"search_index": 0, | |||
"set_only_once": 0, | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"fieldname": "api_secret", | |||
"fieldtype": "Password", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_list_view": 0, | |||
"label": "API Secret", | |||
"length": 0, | |||
"no_copy": 0, | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"read_only": 0, | |||
"report_hide": 0, | |||
"reqd": 1, | |||
"search_index": 0, | |||
"set_only_once": 0, | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"description": "Mention transaction completion page URL", | |||
"fieldname": "redirect_to", | |||
"fieldtype": "Data", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_list_view": 0, | |||
"label": "Redirect To", | |||
"length": 0, | |||
"no_copy": 0, | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"read_only": 0, | |||
"report_hide": 0, | |||
"reqd": 0, | |||
"search_index": 0, | |||
"set_only_once": 0, | |||
"unique": 0 | |||
} | |||
], | |||
"hide_heading": 0, | |||
"hide_toolbar": 0, | |||
"idx": 0, | |||
"image_view": 0, | |||
"in_create": 1, | |||
"in_dialog": 0, | |||
"is_submittable": 0, | |||
"issingle": 1, | |||
"istable": 0, | |||
"max_attachments": 0, | |||
"modified": "2016-09-26 02:00:03.604912", | |||
"modified_by": "Administrator", | |||
"module": "Integrations", | |||
"name": "Razorpay Settings", | |||
"name_case": "", | |||
"owner": "Administrator", | |||
"permissions": [ | |||
{ | |||
"amend": 0, | |||
"apply_user_permissions": 0, | |||
"cancel": 0, | |||
"create": 1, | |||
"delete": 1, | |||
"email": 1, | |||
"export": 1, | |||
"if_owner": 0, | |||
"import": 0, | |||
"permlevel": 0, | |||
"print": 1, | |||
"read": 1, | |||
"report": 0, | |||
"role": "System Manager", | |||
"set_user_permissions": 0, | |||
"share": 1, | |||
"submit": 0, | |||
"write": 1 | |||
} | |||
], | |||
"quick_entry": 0, | |||
"read_only": 1, | |||
"read_only_onload": 0, | |||
"sort_field": "modified", | |||
"sort_order": "DESC", | |||
"track_seen": 0 | |||
} |
@@ -1,6 +1,13 @@ | |||
# -*- coding: utf-8 -*- | |||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors | |||
# License: GNU General Public License v3. See license.txt | |||
# Copyright (c) 2015, Frappe Technologies and contributors | |||
# For license information, please see license.txt | |||
from __future__ import unicode_literals | |||
import frappe | |||
from frappe.utils import get_url, call_hook_method | |||
from frappe import _ | |||
import urllib, json | |||
from frappe.integration_broker.doctype.integration_service.integration_service import IntegrationService | |||
""" | |||
# Integrating RazorPay | |||
@@ -50,31 +57,11 @@ payment_status - payment gateway will put payment status on callback. | |||
For razorpay payment status is Authorized | |||
""" | |||
from __future__ import unicode_literals | |||
import frappe | |||
from frappe import _ | |||
import urllib, json | |||
from frappe.utils import get_url, call_hook_method | |||
from frappe.integration_broker.integration_controller import IntegrationController | |||
class Controller(IntegrationController): | |||
service_name = 'Razorpay' | |||
parameters_template = [ | |||
{ | |||
"label": "API Key", | |||
'fieldname': 'api_key', | |||
'fieldtype': "Data", | |||
'reqd': 1 | |||
}, | |||
{ | |||
"label": "API Secret", | |||
'fieldname': 'api_secret', | |||
'fieldtype': "Password", | |||
'reqd': 1 | |||
} | |||
] | |||
# do also changes in razorpay.js scheduler job helper | |||
class RazorpaySettings(IntegrationService): | |||
service_name = "Razorpay" | |||
supported_currencies = ["INR"] | |||
scheduled_jobs = [ | |||
{ | |||
"all": [ | |||
@@ -82,48 +69,41 @@ class Controller(IntegrationController): | |||
] | |||
} | |||
] | |||
js = "assets/frappe/js/integrations/razorpay.js" | |||
supported_currencies = ["INR"] | |||
def enable(self, parameters, use_test_account=0): | |||
def validate(self): | |||
if not self.flags.ignore_mandatory: | |||
self.validate_razorpay_credentails() | |||
def on_update(self): | |||
pass | |||
def enable(self): | |||
call_hook_method('payment_gateway_enabled', gateway='Razorpay') | |||
self.parameters = parameters | |||
self.validate_razorpay_credentails() | |||
if not self.flags.ignore_mandatory: | |||
self.validate_razorpay_credentails() | |||
def validate_razorpay_credentails(self): | |||
razorpay_settings = self.get_settings() | |||
if razorpay_settings.get("api_key"): | |||
if self.api_key and self.api_secret: | |||
try: | |||
self.get_request(url="https://api.razorpay.com/v1/payments", | |||
auth=(razorpay_settings.api_key, razorpay_settings.api_secret)) | |||
auth=(self.api_key, self.get_password(fieldname="api_secret", raise_exception=False))) | |||
except Exception: | |||
frappe.throw(_("Seems API Key or API Secret is wrong !!!")) | |||
def validate_transaction_currency(self, currency): | |||
if currency not in self.supported_currencies: | |||
frappe.throw(_("Please select another payment method. {0} does not support transactions in currency '{1}'").format(self.service_name, currency)) | |||
def get_payment_url(self, **kwargs): | |||
return get_url("./integrations/razorpay_checkout?{0}".format(urllib.urlencode(kwargs))) | |||
def get_settings(self): | |||
if hasattr(self, "parameters"): | |||
return frappe._dict(self.parameters) | |||
custom_settings_json = frappe.db.get_value("Integration Service", "Razorpay", "custom_settings_json") | |||
if custom_settings_json: | |||
return frappe._dict(json.loads(custom_settings_json)) | |||
def create_request(self, data): | |||
self.data = frappe._dict(data) | |||
try: | |||
self.integration_request = super(Controller, self).create_request(self.data, "Host", \ | |||
self.service_name) | |||
self.integration_request = super(RazorpaySettings, self).create_request(self.data, "Host", \ | |||
"Razorpay") | |||
return self.authorize_payment() | |||
except Exception: | |||
@@ -139,7 +119,6 @@ class Controller(IntegrationController): | |||
The money is deducted from the customer’s account, but will not be transferred to the merchant’s account | |||
until it is explicitly captured by merchant. | |||
""" | |||
settings = self.get_settings() | |||
data = json.loads(self.integration_request.data) | |||
redirect_to = data.get('notes', {}).get('redirect_to') or None | |||
@@ -198,8 +177,8 @@ def capture_payment(is_sandbox=False, sanbox_response=None): | |||
Note: Attempting to capture a payment whose status is not authorized will produce an error. | |||
""" | |||
controller = frappe.get_doc("Integration Service", "Razorpay") | |||
settings = controller.get_parameters() | |||
controller = frappe.get_doc("Razorpay Settings") | |||
for doc in frappe.get_all("Integration Request", filters={"status": "Authorized", | |||
"integration_request_service": "Razorpay"}, fields=["name", "data"]): | |||
try: | |||
@@ -208,7 +187,7 @@ def capture_payment(is_sandbox=False, sanbox_response=None): | |||
else: | |||
data = json.loads(doc.data) | |||
resp = controller.post_request("https://api.razorpay.com/v1/payments/{0}/capture".format(data.get("razorpay_payment_id")), | |||
auth=(settings["api_key"], settings["api_secret"]), data={"amount": data.get("amount")}) | |||
auth=(controller.api_key, controller.get_password("api_secret")), data={"amount": data.get("amount")}) | |||
if resp.get("status") == "captured": | |||
frappe.db.set_value("Integration Request", doc.name, "status", "Completed") | |||
@@ -221,9 +200,47 @@ def capture_payment(is_sandbox=False, sanbox_response=None): | |||
@frappe.whitelist(allow_guest=True, xss_safe=True) | |||
def get_checkout_url(**kwargs): | |||
try: | |||
return Controller().get_payment_url(**kwargs) | |||
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) | |||
@frappe.whitelist() | |||
def get_service_details(): | |||
return """ | |||
<div> | |||
<p> Steps to configure Service | |||
<ol> | |||
<li> Get Razorpay api credentials by login to: | |||
<a href="https://razorpay.com/" target="_blank"> | |||
https://razorpay.com/ | |||
</a> | |||
</li> | |||
<br> | |||
<li> Setup credentials on Razorpay Settings doctype. | |||
Click on | |||
<button class="btn btn-default btn-xs disabled"> Razorpay Settings </button> | |||
top right corner | |||
</li> | |||
<br> | |||
<li> | |||
After saving settings, | |||
<label> | |||
<span class="input-area"> | |||
<input type="checkbox" class="input-with-feedback" checked disabled> | |||
</span> | |||
<span class="label-area small">Enable</span> | |||
</label> | |||
Razorpay Integration Service and Save a document. | |||
</li> | |||
<br> | |||
<li> | |||
To view Razorpays payment logs, | |||
<button class="btn btn-default btn-xs disabled"> Show Log </button> | |||
</li> | |||
</ol> | |||
</div> | |||
""" |
@@ -1,139 +0,0 @@ | |||
import frappe | |||
import ldap, json | |||
from frappe.integration_broker.integration_controller import IntegrationController | |||
from frappe import _ | |||
from frappe.utils import cstr, cint | |||
class Controller(IntegrationController): | |||
service_name = 'LDAP Auth' | |||
parameters_template = [ | |||
{ | |||
"label": "LDAP Server Url", | |||
"fieldname": "ldap_server_url", | |||
"reqd": 1, | |||
"fieldtype": "Data" | |||
}, | |||
{ | |||
"label": "Organizational Unit", | |||
"fieldname": "organizational_unit", | |||
"reqd": 1, | |||
"fieldtype": "Data" | |||
}, | |||
{ | |||
"label": "Base Distinguished Name (DN)", | |||
"fieldname": "base_dn", | |||
"reqd": 1, | |||
"fieldtype": "Data" | |||
}, | |||
{ | |||
"label": "Password for Base DN", | |||
"fieldname": "password", | |||
"reqd": 1, | |||
"fieldtype": "Password" | |||
}, | |||
{ | |||
"label": "Sync frequency from ldap to frappe", | |||
"fieldname": "sync_frequency", | |||
"reqd": 1, | |||
"fieldtype": "Select", | |||
"options": "\nDaily\nWeekly", | |||
} | |||
] | |||
js = "assets/frappe/js/integrations/ldap_auth.js" | |||
def enable(self, parameters, use_test_account=0): | |||
self.parameters = parameters | |||
self.validate_ldap_credentails() | |||
def validate_ldap_credentails(self): | |||
ldap_settings = self.get_settings() | |||
try: | |||
conn = ldap.initialize(ldap_settings.get('ldap_server_url')) | |||
conn.simple_bind_s(ldap_settings.get("base_dn"), ldap_settings.get("password")) | |||
except ldap.LDAPError: | |||
conn.unbind_s() | |||
frappe.throw("Incorrect UserId or Password") | |||
def get_settings(self): | |||
return frappe._dict(self.parameters) | |||
def get_ldap_settings(): | |||
try: | |||
doc = frappe.get_doc("Integration Service", "LDAP Auth") | |||
settings = json.loads(doc.custom_settings_json) | |||
settings.update({ | |||
"enabled": cint(doc.enabled), | |||
"method": "frappe.integrations.ldap_auth.login" | |||
}) | |||
return settings | |||
except Exception: | |||
# this will return blank settings | |||
return frappe._dict() | |||
@frappe.whitelist(allow_guest=True) | |||
def login(): | |||
#### LDAP LOGIN LOGIC ##### | |||
args = frappe.form_dict | |||
user = authenticate_ldap_user(args.usr, args.pwd) | |||
frappe.local.login_manager.user = user.name | |||
frappe.local.login_manager.post_login() | |||
# because of a GET request! | |||
frappe.db.commit() | |||
def authenticate_ldap_user(user=None, password=None): | |||
dn = None | |||
params = {} | |||
settings = get_ldap_settings() | |||
conn = ldap.initialize(settings.get('ldap_server_url')) | |||
print settings | |||
try: | |||
# simple_bind_s is synchronous binding to server, it takes two param DN and password | |||
conn.simple_bind_s(settings.get("base_dn"), settings.get("password")) | |||
print "here" | |||
#search for surnames beginning with a | |||
#available options for how deep a search you want. | |||
#LDAP_SCOPE_BASE, LDAP_SCOPE_ONELEVEL,LDAP_SCOPE_SUBTREE, | |||
result = conn.search_s(settings.get("organizational_unit"), ldap.SCOPE_SUBTREE, | |||
"uid=*{0}".format(user)) | |||
print result | |||
for dn, r in result: | |||
dn = cstr(dn) | |||
params["email"] = cstr(r['mail'][0]) | |||
params["username"] = cstr(r['uid'][0]) | |||
params["first_name"] = cstr(r['cn'][0]) | |||
if dn: | |||
conn.simple_bind_s(dn, password) | |||
return create_user(params) | |||
else: | |||
frappe.throw(_("Not a valid LDAP user")) | |||
except ldap.LDAPError: | |||
conn.unbind_s() | |||
frappe.throw(_("Incorrect UserId or Password")) | |||
def create_user(params): | |||
if frappe.db.exists("User", params["email"]): | |||
return frappe.get_doc("User", params["email"]) | |||
else: | |||
params.update({ | |||
"doctype": "User", | |||
"send_welcome_email": 0, | |||
"language": "", | |||
"user_type": "System User", | |||
"user_roles": [{ | |||
"role": _("Blogger") | |||
}] | |||
}) | |||
user = frappe.get_doc(params).insert(ignore_permissions=True) | |||
frappe.db.commit() | |||
return user | |||
@@ -143,3 +143,4 @@ execute:frappe.core.doctype.language.language.update_language_names() | |||
execute:frappe.db.set_value("Print Settings", "Print Settings", "add_draft_heading", 1) | |||
frappe.patches.v7_0.cleanup_list_settings | |||
execute:frappe.db.set_default('language', '') | |||
frappe.patches.v7_1.refactor_integration_broker |
@@ -0,0 +1,52 @@ | |||
# -*- coding: utf-8 -*- | |||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors | |||
# License: GNU General Public License v3. See license.txt | |||
from __future__ import unicode_literals | |||
import frappe | |||
import json | |||
def execute(): | |||
for doctype_name in ["Razorpay Log", "Razorpay Payment", "Razorpay Settings"]: | |||
delete_doc("DocType", doctype_name) | |||
reload_doctypes() | |||
setup_services() | |||
def delete_doc(doctype, doctype_name): | |||
frappe.delete_doc(doctype, doctype_name) | |||
def reload_doctypes(): | |||
for doctype in ("razorpay_settings", "paypal_settings", "dropbox_settings", "ldap_settings"): | |||
frappe.reload_doc("integrations", "doctype", doctype) | |||
def setup_services(): | |||
for service in [{"old_name": "Razorpay", "new_name": "Razorpay"}, | |||
{"old_name": "PayPal", "new_name": "PayPal"}, | |||
{"old_name": "Dropbox Integration", "new_name": "Dropbox"}, | |||
{"old_name": "LDAP Auth", "new_name": "LDAP"}]: | |||
try: | |||
service_doc = frappe.get_doc("Integration Service", service["old_name"]) | |||
settings = json.loads(service_doc.custom_settings_json) | |||
service_settings = frappe.new_doc("{0} Settings".format(service["new_name"])) | |||
service_settings.update(settings) | |||
service_settings.flags.ignore_mandatory = True | |||
service_settings.save(ignore_permissions=True) | |||
if service["old_name"] in ["Dropbox Integration", "LDAP Auth"]: | |||
delete_doc("Integration Service", service["old_name"]) | |||
new_service_doc = frappe.get_doc({ | |||
"doctype": "Integration Service", | |||
"service": service["new_name"], | |||
"enabled": 1 | |||
}) | |||
new_service_doc.flags.ignore_mandatory = True | |||
new_service_doc.save(ignore_permissions=True) | |||
except Exception: | |||
pass |
@@ -1,48 +0,0 @@ | |||
frappe.provide("frappe.integration_service") | |||
frappe.integration_service.dropbox_integration = { | |||
load: function(frm) { | |||
new frappe.integration_service.DropboxIntegration(frm) | |||
}, | |||
scheduler_job_helper: function(){ | |||
return { | |||
"Daily": "Take backup of database and files to dropbox on daily basis", | |||
"Weekly": "Take backup of database and files to dropbox on weekly basis" | |||
} | |||
} | |||
} | |||
frappe.integration_service.DropboxIntegration = Class.extend({ | |||
init: function(frm) { | |||
this.frm = frm; | |||
this.frm.toggle_display("use_test_account", false); | |||
if(this.frm.doc.service == "Dropbox Integration" && this.frm.doc.enabled && !this.frm.doc.__islocal){ | |||
this.allow_dropbox_acess(frm); | |||
this.take_backup(frm); | |||
} | |||
}, | |||
allow_dropbox_acess: function(frm) { | |||
this.frm.add_custom_button(__("Allow Dropbox Access"), function(frm){ | |||
frappe.call({ | |||
method: "frappe.integrations.dropbox_integration.get_dropbox_authorize_url", | |||
freeze: true, | |||
callback: function(r) { | |||
if(!r.exc) { | |||
window.open(r.message.url); | |||
} | |||
} | |||
}) | |||
}).addClass("btn-primary") | |||
}, | |||
take_backup: function(frm) { | |||
var me = this; | |||
this.frm.add_custom_button(__("Take Backup Now"), function(frm){ | |||
frappe.call({ | |||
method: "frappe.integrations.dropbox_integration.take_backup", | |||
freeze: true | |||
}) | |||
}).addClass("btn-primary") | |||
} | |||
}) |
@@ -1,15 +0,0 @@ | |||
frappe.provide("frappe.integration_service") | |||
frappe.integration_service.ldap_auth = { | |||
load: function(frm) { | |||
new frappe.integration_service.ldapAuth(frm) | |||
} | |||
} | |||
frappe.integration_service.ldapAuth = Class.extend({ | |||
init:function(frm){ | |||
this.frm = frm; | |||
this.frm.toggle_display("use_test_account", false); | |||
} | |||
}) | |||
@@ -1,21 +0,0 @@ | |||
frappe.provide("frappe.integration_service") | |||
frappe.integration_service.paypal = { | |||
load: function(frm) { | |||
new frappe.integration_service.PayPal(frm) | |||
} | |||
} | |||
frappe.integration_service.PayPal = Class.extend({ | |||
init:function(frm){ | |||
this.frm = frm; | |||
this.show_logs(); | |||
}, | |||
show_logs: function(){ | |||
this.frm.add_custom_button(__("Show Log"), function(frm){ | |||
frappe.route_options = {"integration_request_service": "PayPal"}; | |||
frappe.set_route("List", "Integration Request"); | |||
}).addClass("btn-primary") | |||
} | |||
}) | |||
@@ -6,8 +6,6 @@ from frappe import _ | |||
from frappe.utils import flt | |||
import json | |||
from frappe.integrations.razorpay import Controller | |||
no_cache = 1 | |||
no_sitemap = 1 | |||
@@ -16,7 +14,7 @@ expected_keys = ('amount', 'title', 'description', 'reference_doctype', 'referen | |||
def get_context(context): | |||
context.no_cache = 1 | |||
context.api_key = Controller().get_settings().api_key | |||
context.api_key = frappe.db.get_value("Razorpay Settings", None, "api_key") | |||
# all these keys exist in form_dict | |||
if not (set(expected_keys) - set(frappe.form_dict.keys())): | |||
@@ -43,4 +41,6 @@ def make_payment(razorpay_payment_id, options, reference_doctype, reference_docn | |||
"reference_doctype": reference_doctype | |||
}) | |||
return Controller().create_request(data) | |||
data = frappe.get_doc("Razorpay Settings").create_request(data) | |||
frappe.db.commit() | |||
return data |
@@ -8,7 +8,7 @@ from frappe.utils.oauth import get_oauth2_authorize_url, get_oauth_keys, login_v | |||
import json | |||
from frappe import _ | |||
from frappe.auth import LoginManager | |||
from frappe.integrations.ldap_auth import get_ldap_settings | |||
from frappe.integrations.doctype.ldap_settings.ldap_settings import get_ldap_settings | |||
no_cache = True | |||
@@ -38,4 +38,3 @@ zxcvbn | |||
psutil | |||
unittest-xml-reporting | |||
xlwt | |||
python-ldap |