fix: event consumer authentication

This commit is contained in:
Rucha Mahabal 2019-09-09 00:57:08 +05:30
parent dff86d5c23
commit ee2e1936d3
7 changed files with 132 additions and 54 deletions

View file

@ -178,20 +178,25 @@ def validate_auth_via_api_keys():
def validate_api_key_secret(api_key, api_secret, frappe_authorization_source=None):
""" frappe_authorization_source to provide api key and secret for a doctype apart from User """
if not frappe_authorization_source:
frappe_authorization_source = 'User'
doc = frappe.db.get_value(
doctype=frappe_authorization_source,
filters={"api_key": api_key},
fieldname=["name"]
)
form_dict = frappe.local.form_dict
doc_secret = frappe.utils.password.get_decrypted_password(frappe_authorization_source, doc, fieldname="api_secret")
if api_secret == doc_secret:
fieldname = 'name' if frappe_authorization_source == 'User' else 'user'
if frappe_authorization_source == 'User':
fieldname = 'name'
else:
fieldname = 'user'
user = frappe.db.get_value(frappe_authorization_source, doc, fieldname)
frappe.set_user(user)
frappe.local.form_dict = form_dict
user = frappe.db.get_value(
doctype="User",
filters={"api_key": api_key},
fieldname=["name"]
)
form_dict = frappe.local.form_dict
user_secret = frappe.utils.password.get_decrypted_password ("User", user, fieldname='api_secret')
if api_secret == user_secret:
frappe.set_user(user)
frappe.local.form_dict = form_dict
else:
doc = frappe.db.get_value(
doctype=frappe_authorization_source,
filters={"api_key": api_key},
fieldname=["name"]
)
form_dict = frappe.local.form_dict
doc_secret = frappe.utils.password.get_decrypted_password (frappe_authorization_source, doc, fieldname='api_secret')
if api_secret == doc_secret:
user = frappe.db.get_value(frappe_authorization_source, doc, 'user')
frappe.set_user(user)
frappe.local.form_dict = form_dict

View file

@ -6,7 +6,10 @@
"engine": "InnoDB",
"field_order": [
"subscribed_doctypes",
"callback_url"
"callback_url",
"user",
"api_key",
"api_secret"
],
"fields": [
{
@ -21,11 +24,29 @@
"fieldname": "subscribed_doctypes",
"fieldtype": "Table",
"label": "Subscribed Doctypes",
"options": "Event Subscribed DocType",
"options": "Event Subscribed DocType"
},
{
"fieldname": "api_key",
"fieldtype": "Data",
"label": "API Key",
"read_only": 1
},
{
"fieldname": "api_secret",
"fieldtype": "Password",
"label": "API Secret",
"read_only": 1
},
{
"fieldname": "user",
"fieldtype": "Link",
"label": "Event Subscriber",
"options": "User",
"reqd": 1
}
],
"modified": "2019-08-29 21:00:03.302463",
"modified": "2019-09-08 22:25:29.141335",
"modified_by": "Administrator",
"module": "Events Streaming",
"name": "Event Consumer",

View file

@ -3,8 +3,30 @@
# For license information, please see license.txt
from __future__ import unicode_literals
# import frappe
import frappe
import requests
import time
import json
from frappe.model.document import Document
from frappe.frappeclient import FrappeClient
class EventConsumer(Document):
pass
@frappe.whitelist(allow_guest=True)
def register_consumer(event_consumer, subscribed_doctypes, user):
consumer = frappe.new_doc('Event Consumer')
consumer.callback_url = event_consumer
consumer.user = user
subscribed_doctypes = json.loads(subscribed_doctypes)
for entry in subscribed_doctypes:
consumer.append('subscribed_doctypes',{
'ref_doctype': entry
})
api_key = frappe.generate_hash(length=10)
api_secret = frappe.generate_hash(length=10)
consumer.api_key = api_key
consumer.api_secret = api_secret
consumer.insert(ignore_permissions = True)
return (api_key, api_secret)

View file

@ -7,7 +7,10 @@
"field_order": [
"producer_url",
"subscribed_doctypes",
"last_update"
"last_update",
"user",
"api_key",
"api_secret"
],
"fields": [
{
@ -22,18 +25,35 @@
"fieldname": "subscribed_doctypes",
"fieldtype": "Table",
"label": "Subscribed Doctypes",
"options": "Event Subscribed DocType",
"reqd": 1
"options": "Event Subscribed DocType"
},
{
"fieldname": "last_update",
"fieldtype": "Data",
"label": "Last Update",
"read_only": 1,
"read_only": 1
},
{
"fieldname": "api_key",
"fieldtype": "Data",
"label": "API Key",
"read_only": 1
},
{
"fieldname": "api_secret",
"fieldtype": "Password",
"label": "API Secret",
"read_only": 1
},
{
"fieldname": "user",
"fieldtype": "Link",
"label": "Event Subscriber",
"options": "User",
"reqd": 1
}
],
"modified": "2019-08-30 12:17:30.264969",
"modified": "2019-09-08 22:25:42.372289",
"modified_by": "Administrator",
"module": "Events Streaming",
"name": "Event Producer",

View file

@ -11,31 +11,34 @@ from frappe.frappeclient import FrappeClient
class EventProducer(Document):
def after_insert(self):
self.update_event_consumer()
self.create_event_consumer()
def on_update(self):
self.update_event_consumer()
def update_event_consumer(self):
producer_site = get_producer_site(self.producer_url)
try:
event_consumer = producer_site.get_doc('Event Consumer', get_current_node())
event_consumer.subscribed_doctypes = []
for entry in self.subscribed_doctypes:
event_consumer.subscribed_doctypes.append({
'ref_doctype': entry.ref_doctype
})
event_consumer.event_subscriber = self.event_subscriber
producer_site.update(event_consumer)
except Exception:
consumer = frappe.new_doc('Event Consumer')
consumer.callback_url = get_current_node()
for entry in self.subscribed_doctypes:
consumer.append('subscribed_doctypes', {
'ref_doctype': entry.ref_doctype
})
consumer.event_subscriber = self.event_subscriber
producer_site.insert(consumer)
event_consumer = producer_site.get_doc('Event Consumer', get_current_node())
event_consumer.subscribed_doctypes = []
for entry in self.subscribed_doctypes:
event_consumer.subscribed_doctypes.append({
'ref_doctype': entry.ref_doctype
})
event_consumer.user = self.user
producer_site.update(event_consumer)
def create_event_consumer(self):
'''register event consumer on producer site'''
producer_site = FrappeClient(self.producer_url)
subscribed_doctypes = []
for entry in self.subscribed_doctypes:
subscribed_doctypes.append(entry.ref_doctype)
(api_key, api_secret) = producer_site.post_request({
'cmd': 'frappe.events_streaming.doctype.event_consumer.event_consumer.register_consumer',
'event_consumer': get_current_node(),
'subscribed_doctypes': json.dumps(subscribed_doctypes),
'user': self.user
})
self.db_set('api_key', api_key)
self.db_set('api_secret', api_secret)
def get_current_node():
current_node = frappe.utils.get_url()
@ -46,7 +49,13 @@ def get_current_node():
return current_node
def get_producer_site(producer_url):
producer_site = FrappeClient(producer_url, 'Administrator', 'root')
producer_doc = frappe.get_doc('Event Producer', producer_url)
producer_site = FrappeClient(
url=producer_url,
api_key=producer_doc.api_key,
api_secret=producer_doc.get_password('api_secret'),
frappe_authorization_source='Event Consumer'
)
return producer_site
@frappe.whitelist()

View file

@ -17,10 +17,10 @@
}
],
"istable": 1,
"modified": "2019-08-29 11:35:00.625815",
"modified": "2019-09-08 20:52:52.660698",
"modified_by": "Administrator",
"module": "Events Streaming",
"name": "Event Subscribed DocType",
"name": "Event Subscribed Doctype",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,

View file

@ -58,9 +58,10 @@ class FrappeClient(object):
token = b64encode('{}:{}'. format(api_key, api_secret))
auth_header = {'Authorization': 'Basic {}'.format(token)}
self.session.headers.update(auth_header)
if frappe_authorization_source:
auth_source = {'Frappe-Authorization-Source': frappe_authorization_source}
self.session.headers.update(auth_source)
if not frappe_authorization_source:
frappe_authorization_source = 'User'
auth_source = {'Frappe-Authorization-Source': frappe_authorization_source}
self.session.headers.update(auth_source)
def logout(self):
'''Logout session'''