def test_auth_via_api_key_secret(self): # generate API key and API secret for administrator keys = generate_keys("Administrator") frappe.db.commit() generated_secret = frappe.utils.password.get_decrypted_password( "User", "Administrator", fieldname='api_secret' ) api_key = frappe.db.get_value("User", "Administrator", "api_key") header = {"Authorization": "token {}:{}".format(api_key, generated_secret)} res = requests.post(get_url() + "/api/method/frappe.auth.get_logged_user", headers=header) self.assertEqual(res.status_code, 200) self.assertEqual("Administrator", res.json()["message"]) self.assertEqual(keys['api_secret'], generated_secret) header = {"Authorization": "Basic {}".format(base64.b64encode(frappe.safe_encode("{}:{}".format(api_key, generated_secret))).decode())} res = requests.post(get_url() + "/api/method/frappe.auth.get_logged_user", headers=header) self.assertEqual(res.status_code, 200) self.assertEqual("Administrator", res.json()["message"]) # Valid api key, invalid api secret api_secret = "ksk&93nxoe3os" header = {"Authorization": "token {}:{}".format(api_key, api_secret)} res = requests.post(get_url() + "/api/method/frappe.auth.get_logged_user", headers=header) self.assertEqual(res.status_code, 403) # random api key and api secret api_key = "@3djdk3kld" api_secret = "ksk&93nxoe3os" header = {"Authorization": "token {}:{}".format(api_key, api_secret)} res = requests.post(get_url() + "/api/method/frappe.auth.get_logged_user", headers=header) self.assertEqual(res.status_code, 401)
def get_payment_link(currency, refno, amount, verify=True): settings = frappe.get_doc("Datatrans Settings", "Datatrans Settings") payload = { "currency": currency, "refno": refno, "amount": float(amount), "paymentMethods": settings.get_payment_method_list(), "redirect": { "successUrl": settings.success_url or get_url(), "errorUrl": settings.error_url or get_url(), "cancelUrl": settings.cancel_url or get_url() } } auth = HTTPBasicAuth( settings.username, get_decrypted_password("Datatrans Settings", "Datatrans Settings", "password", False)) r = requests.post("{0}/transactions".format(settings.endpoint), verify=verify, auth=auth, json=payload) return {'success': 1, 'status': r.status_code, 'result': r.text}
def update_consumer_status(self): consumer_site = get_consumer_site(self.callback_url) event_producer = consumer_site.get_doc('Event Producer', get_url()) event_producer = frappe._dict(event_producer) config = event_producer.producer_doctypes event_producer.producer_doctypes = [] for entry in config: if entry.get('has_mapping'): ref_doctype = consumer_site.get_value( 'Document Type Mapping', 'remote_doctype', entry.get('mapping')).get('remote_doctype') else: ref_doctype = entry.get('ref_doctype') entry['status'] = frappe.db.get_value( 'Event Consumer Document Type', { 'parent': self.name, 'ref_doctype': ref_doctype }, 'status') event_producer.producer_doctypes = config # when producer doc is updated it updates the consumer doc # set flag to avoid deadlock event_producer.incoming_change = True consumer_site.update(event_producer)
def update_event_consumer(self): if self.is_producer_online(): producer_site = get_producer_site(self.producer_url) event_consumer = producer_site.get_doc("Event Consumer", get_url()) event_consumer = frappe._dict(event_consumer) if event_consumer: config = event_consumer.consumer_doctypes event_consumer.consumer_doctypes = [] for entry in self.producer_doctypes: if entry.has_mapping: # if mapping, subscribe to remote doctype on consumer's site ref_doctype = frappe.db.get_value("Document Type Mapping", entry.mapping, "remote_doctype") else: ref_doctype = entry.ref_doctype event_consumer.consumer_doctypes.append( { "ref_doctype": ref_doctype, "status": get_approval_status(config, ref_doctype), "unsubscribed": entry.unsubscribe, "condition": entry.condition, } ) event_consumer.user = self.user event_consumer.incoming_change = True producer_site.update(event_consumer)
def update_event_consumer(self): if self.is_producer_online(): producer_site = get_producer_site(self.producer_url) event_consumer = producer_site.get_doc('Event Consumer', get_url()) event_consumer = frappe._dict(event_consumer) if event_consumer: config = event_consumer.consumer_doctypes event_consumer.consumer_doctypes = [] for entry in self.producer_doctypes: if entry.has_mapping: # if mapping, subscribe to remote doctype on consumer's site ref_doctype = frappe.db.get_value( 'Document Type Mapping', entry.mapping, 'remote_doctype') else: ref_doctype = entry.ref_doctype event_consumer.consumer_doctypes.append({ 'ref_doctype': ref_doctype, 'status': get_approval_status(config, ref_doctype) }) if frappe.flags.in_test: event_consumer.in_test = True event_consumer.user = self.user event_consumer.incoming_change = True producer_site.update(event_consumer)
def test_get_value(self): server = FrappeClient(get_url(), "Administrator", "admin", verify=False) frappe.db.sql("delete from `tabNote` where title = 'get_value'") frappe.db.commit() test_content = "test get value" server.insert_many([ { "doctype": "Note", "public": True, "title": "get_value", "content": test_content }, ]) self.assertEqual( server.get_value("Note", "content", { "title": "get_value" }).get('content'), test_content) name = server.get_value("Note", "name", { "title": "get_value" }).get('name') # test by name self.assertEqual( server.get_value("Note", "content", name).get('content'), test_content) self.assertRaises( FrappeException, server.get_value, "Note", "(select (password) from(__Auth) order by name desc limit 1)", {"title": "get_value"})
def get_request_data(doc): """ This function is called when Consumer site is making `EventConsumer` on producer site. This function is actually defined in frappe.event_streaming.doctype.event_producer.event_producer.EventProducer.get_request_data We are patching the function so that we can send the `condition` field while creating the `Consumer` on Producer site. """ consumer_doctypes = [] for entry in doc.producer_doctypes: if entry.has_mapping: # if mapping, subscribe to remote doctype on consumer's site consumer_doctypes.append({ "ref_doctype": frappe.db.get_value('Document Type Mapping', entry.mapping, 'remote_doctype'), "condition": entry.condition }) else: consumer_doctypes.append({ "ref_doctype": entry.ref_doctype, "condition": entry.condition }) return { 'event_consumer': get_url(), 'consumer_doctypes': frappe.as_json(consumer_doctypes), 'user': doc.user, 'in_test': frappe.flags.in_test }
def notify(consumer): """notify individual event consumers about a new update""" consumer_status = consumer.get_consumer_status() if consumer_status == 'online': try: client = get_consumer_site(consumer.callback_url) client.post_request({ 'cmd': 'frappe.event_streaming.doctype.event_producer.event_producer.new_event_notification', 'producer_url': get_url() }) consumer.flags.notified = True except Exception: consumer.flags.notified = False else: consumer.flags.notified = False # enqueue another job if the site was not notified if not consumer.flags.notified: enqueued_method = 'frappe.event_streaming.doctype.event_consumer.event_consumer.notify' jobs = get_jobs() if not jobs or enqueued_method not in jobs[ frappe.local.site] and not consumer.flags.notifed: frappe.enqueue(enqueued_method, queue='long', enqueue_after_commit=True, **{'consumer': consumer})
def test_list_docs(self): server = FrappeClient(get_url(), "Administrator", "admin", verify=False) doc_list = server.get_list("Note") self.assertTrue(len(doc_list))
def pull_producer_data(): """Fetch data from producer node.""" response = requests.get(get_url()) if response.status_code == 200: for event_producer in frappe.get_all('Event Producer'): pull_from_node(event_producer.name) return 'success' return None
def test_create_doc(self): server = FrappeClient(get_url(), "Administrator", "admin", verify=False) frappe.db.delete("Note", {"title": "test_create"}) frappe.db.commit() server.insert({"doctype": "Note", "public": True, "title": "test_create"}) self.assertTrue(frappe.db.get_value('Note', {'title': 'test_create'}))
def test_update_child_doc(self): server = FrappeClient(get_url(), "Administrator", "admin", verify=False) frappe.db.sql( "delete from `tabContact` where first_name = 'George' and last_name = 'Steevens'" ) frappe.db.sql( "delete from `tabContact` where first_name = 'William' and last_name = 'Shakespeare'" ) frappe.db.sql( "delete from `tabCommunication` where reference_doctype = 'Event'") frappe.db.sql( "delete from `tabCommunication Link` where link_doctype = 'Contact'" ) frappe.db.sql( "delete from `tabEvent` where subject = 'Sing a song of sixpence'") frappe.db.sql( "delete from `tabEvent Participants` where reference_doctype = 'Contact'" ) frappe.db.commit() # create multiple contacts server.insert_many([{ "doctype": "Contact", "first_name": "George", "last_name": "Steevens" }, { "doctype": "Contact", "first_name": "William", "last_name": "Shakespeare" }]) # create an event with one of the created contacts event = server.insert({ "doctype": "Event", "subject": "Sing a song of sixpence", "event_participants": [{ "reference_doctype": "Contact", "reference_docname": "George Steevens" }] }) # update the event's contact to the second contact server.update({ "doctype": "Event Participants", "name": event.get("event_participants")[0].get("name"), "reference_docname": "William Shakespeare" }) # the change should run the parent document's validations and # create a Communication record with the new contact self.assertTrue( frappe.db.exists("Communication Link", {"link_name": "William Shakespeare"}))
def get_updates(producer_site, last_update, doctypes): """Get all updates generated after the last update timestamp""" docs = producer_site.post_request({ 'cmd': 'frappe.event_streaming.doctype.event_update_log.event_update_log.get_update_logs_for_consumer', 'event_consumer': get_url(), 'doctypes': frappe.as_json(doctypes), 'last_update': last_update }) return [frappe._dict(d) for d in (docs or [])]
def test_get_doc(self): server = FrappeClient(get_url(), "Administrator", "admin", verify=False) frappe.db.delete("Note", {"title": "get_this"}) frappe.db.commit() server.insert_many([ {"doctype": "Note", "public": True, "title": "get_this"}, ]) doc = server.get_doc("Note", "get_this") self.assertTrue(doc)
def test_update_doc(self): server = FrappeClient(get_url(), "Administrator", "admin", verify=False) frappe.db.sql("delete from `tabNote` where title in ('Sing','sing')") frappe.db.commit() server.insert({"doctype":"Note", "public": True, "title": "Sing"}) doc = server.get_doc("Note", 'Sing') changed_title = "sing" doc["title"] = changed_title doc = server.update(doc) self.assertTrue(doc["title"] == changed_title)
def test_delete_doc(self): server = FrappeClient(get_url(), "Administrator", "admin", verify=False) frappe.db.sql("delete from `tabNote` where title = 'delete'") frappe.db.commit() server.insert_many([ {"doctype": "Note", "public": True, "title": "delete"}, ]) server.delete("Note", "delete") self.assertFalse(frappe.db.get_value('Note', {'title': 'delete'}))
def get_updates(producer_site, last_update, doctypes): """Get all updates generated after the last update timestamp""" docs = producer_site.post_request({ 'cmd': 'frappe_renovation_docsync.utils.event_producer.get_producer_updates', 'event_consumer': get_url(), 'doctypes': frappe.as_json(doctypes), 'last_update': last_update }) return [frappe._dict(d) for d in docs]
def get_updates(producer_site, last_update, doctypes): """Get all updates generated after the last update timestamp""" docs = producer_site.post_request( { "cmd": "frappe.event_streaming.doctype.event_update_log.event_update_log.get_update_logs_for_consumer", "event_consumer": get_url(), "doctypes": frappe.as_json(doctypes), "last_update": last_update, } ) return [frappe._dict(d) for d in (docs or [])]
def test_update_doc(self): server = FrappeClient(get_url(), "Administrator", "admin", verify=False) frappe.db.delete("Note", {"title": ("in", ("Sing", "sing"))}) frappe.db.commit() server.insert({"doctype":"Note", "public": True, "title": "Sing"}) doc = server.get_doc("Note", 'Sing') changed_title = "sing" doc["title"] = changed_title doc = server.update(doc) self.assertTrue(doc["title"] == changed_title)
def test_create_doc(self): server = FrappeClient(get_url(), "Administrator", "admin", verify=False) frappe.db.sql("delete from `tabNote` where title = 'test_create'") frappe.db.commit() server.insert({ "doctype": "Note", "public": True, "title": "test_create" }) self.assertTrue(frappe.db.get_value("Note", {"title": "test_create"}))
def test_get_single(self): server = FrappeClient(get_url(), "Administrator", "admin", verify=False) server.set_value('Website Settings', 'Website Settings', 'title_prefix', 'test-prefix') self.assertEqual( server.get_value('Website Settings', 'title_prefix', 'Website Settings').get('title_prefix'), 'test-prefix') self.assertEqual( server.get_value('Website Settings', 'title_prefix').get('title_prefix'), 'test-prefix') frappe.db.set_value('Website Settings', None, 'title_prefix', '')
def make(self): """build into msg_root""" headers = { "Subject": strip(self.subject).encode("utf-8"), "From": self.sender.encode("utf-8"), "To": ', '.join(self.recipients).encode("utf-8"), "Date": email.utils.formatdate(), "Reply-To": self.reply_to.encode("utf-8") if self.reply_to else None, "CC": ', '.join(self.cc).encode("utf-8") if self.cc else None, b'X-Frappe-Site': get_url().encode('utf-8') } # reset headers as values may be changed. for key, val in headers.iteritems(): if self.msg_root.has_key(key): del self.msg_root[key] self.msg_root[key] = val
def test_get_single(self): server = FrappeClient(get_url(), "Administrator", "admin", verify=False) server.set_value("Website Settings", "Website Settings", "title_prefix", "test-prefix") self.assertEqual( server.get_value("Website Settings", "title_prefix", "Website Settings").get("title_prefix"), "test-prefix", ) self.assertEqual( server.get_value("Website Settings", "title_prefix").get("title_prefix"), "test-prefix") frappe.db.set_value("Website Settings", None, "title_prefix", "")
def get_request_data(self): consumer_doctypes = [] for entry in self.producer_doctypes: if entry.has_mapping: # if mapping, subscribe to remote doctype on consumer's site consumer_doctypes.append( frappe.db.get_value('Document Type Mapping', entry.mapping, 'remote_doctype')) else: consumer_doctypes.append(entry.ref_doctype) return { 'event_consumer': get_url(), 'consumer_doctypes': json.dumps(consumer_doctypes), 'user': self.user, 'in_test': frappe.flags.in_test }
def test_insert_many(self): server = FrappeClient(get_url(), "Administrator", "admin", verify=False) frappe.db.delete("Note", {"title": ("in", ('Sing','a','song','of','sixpence'))}) frappe.db.commit() server.insert_many([ {"doctype": "Note", "public": True, "title": "Sing"}, {"doctype": "Note", "public": True, "title": "a"}, {"doctype": "Note", "public": True, "title": "song"}, {"doctype": "Note", "public": True, "title": "of"}, {"doctype": "Note", "public": True, "title": "sixpence"}, ]) self.assertTrue(frappe.db.get_value('Note', {'title': 'Sing'})) self.assertTrue(frappe.db.get_value('Note', {'title': 'a'})) self.assertTrue(frappe.db.get_value('Note', {'title': 'song'})) self.assertTrue(frappe.db.get_value('Note', {'title': 'of'})) self.assertTrue(frappe.db.get_value('Note', {'title': 'sixpence'}))
def get_request_data(self): consumer_doctypes = [] for entry in self.producer_doctypes: if entry.has_mapping: # if mapping, subscribe to remote doctype on consumer's site dt = frappe.db.get_value("Document Type Mapping", entry.mapping, "remote_doctype") else: dt = entry.ref_doctype consumer_doctypes.append({"doctype": dt, "condition": entry.condition}) user_key = frappe.db.get_value("User", self.user, "api_key") user_secret = get_decrypted_password("User", self.user, "api_secret") return { "event_consumer": get_url(), "consumer_doctypes": json.dumps(consumer_doctypes), "user": self.user, "api_key": user_key, "api_secret": user_secret, }
def test_insert_many(self): server = FrappeClient(get_url(), "Administrator", "admin", verify=False) frappe.db.sql( "delete from `tabNote` where title in ('Sing','a','song','of','sixpence')" ) frappe.db.commit() server.insert_many([ { "doctype": "Note", "public": True, "title": "Sing" }, { "doctype": "Note", "public": True, "title": "a" }, { "doctype": "Note", "public": True, "title": "song" }, { "doctype": "Note", "public": True, "title": "of" }, { "doctype": "Note", "public": True, "title": "sixpence" }, ]) self.assertTrue(frappe.db.get_value("Note", {"title": "Sing"})) self.assertTrue(frappe.db.get_value("Note", {"title": "a"})) self.assertTrue(frappe.db.get_value("Note", {"title": "song"})) self.assertTrue(frappe.db.get_value("Note", {"title": "of"})) self.assertTrue(frappe.db.get_value("Note", {"title": "sixpence"}))
def get_request_data(self): consumer_doctypes = [] for entry in self.producer_doctypes: if entry.has_mapping: # if mapping, subscribe to remote doctype on consumer's site consumer_doctypes.append( frappe.db.get_value('Document Type Mapping', entry.mapping, 'remote_doctype')) else: consumer_doctypes.append(entry.ref_doctype) user_key = frappe.db.get_value('User', self.user, 'api_key') user_secret = get_decrypted_password('User', self.user, 'api_secret') return { 'event_consumer': get_url(), 'consumer_doctypes': json.dumps(consumer_doctypes), 'user': self.user, 'api_key': user_key, 'api_secret': user_secret }
def update_event_consumer(self): """ This function is called when Consumer wants to update the `EventConsumer` doc on Producer This overrides the frappe function: frappe.event_streaming.doctype.event_producer.event_producer.EventProducer.update_event_consumer We are patching this function to update the Conditions along with the new doctypes """ if self.is_producer_online(): producer_site = get_producer_site(self.producer_url) event_consumer = producer_site.get_doc('Event Consumer', get_url()) event_consumer = frappe._dict(event_consumer) if event_consumer: config = event_consumer.consumer_doctypes event_consumer.consumer_doctypes = [] for entry in self.producer_doctypes: if entry.has_mapping: # if mapping, subscribe to remote doctype on consumer's site ref_doctype = frappe.db.get_value('Document Type Mapping', entry.mapping, 'remote_doctype') else: ref_doctype = entry.ref_doctype event_consumer.consumer_doctypes.append({ 'ref_doctype': ref_doctype, 'condition': entry.condition, 'status': get_approval_status(config, ref_doctype) }) if frappe.flags.in_test: event_consumer.in_test = True event_consumer.user = self.user event_consumer.incoming_change = True producer_site.update(event_consumer)
def update_consumer_status(self): consumer_site = get_consumer_site(self.callback_url) event_producer = consumer_site.get_doc("Event Producer", get_url()) event_producer = frappe._dict(event_producer) config = event_producer.producer_doctypes event_producer.producer_doctypes = [] for entry in config: if entry.get("has_mapping"): ref_doctype = consumer_site.get_value( "Document Type Mapping", "remote_doctype", entry.get("mapping") ).get("remote_doctype") else: ref_doctype = entry.get("ref_doctype") entry["status"] = frappe.db.get_value( "Event Consumer Document Type", {"parent": self.name, "ref_doctype": ref_doctype}, "status" ) event_producer.producer_doctypes = config # when producer doc is updated it updates the consumer doc # set flag to avoid deadlock event_producer.incoming_change = True consumer_site.update(event_producer)