diff --git a/landa/water_body_management/doctype/firebase_settings/firebase_settings.js b/landa/water_body_management/doctype/firebase_settings/firebase_settings.js index c3590404..0120a31b 100644 --- a/landa/water_body_management/doctype/firebase_settings/firebase_settings.js +++ b/landa/water_body_management/doctype/firebase_settings/firebase_settings.js @@ -3,44 +3,35 @@ frappe.ui.form.on("Firebase Settings", { refresh: (frm) => { - if (frm.doc.enable_firebase_notifications) { - frm.events.upload_api_file_button(frm); - } - }, - - enable_firebase_notifications: (frm) => { - if (frm.doc.enable_firebase_notifications) { - frm.events.upload_api_file_button(frm); - } else { - frm.remove_custom_button(__("Upload Firebase API File")) - } + frm.call("needs_credentials").then(({ message }) => { + if (message) { + frm.events.add_upload_credentials_button(frm); + } + }); }, - upload_api_file_button: (frm) => { - frm.add_custom_button(__("Upload Firebase API File"), function() { + add_upload_credentials_button: (frm) => { + frm.add_custom_button(__("Upload Firebase Credentials"), function () { new frappe.ui.FileUploader({ + method: "landa.water_body_management.doctype.firebase_settings.firebase_settings.upload_api_file", allow_multiple: false, restrictions: { - allowed_file_types: [".json"] + allowed_file_types: [".json"], }, - on_success(file_doc) { - frappe.call({ - method: "landa.water_body_management.doctype.firebase_settings.firebase_settings.upload_api_file", - args: { - file_url: file_doc.file_url, - file_id: file_doc.name - }, - freeze: true, - freeze_message: __("Configuring Firebase API ..."), - callback: function(r) { - if (r.message && !r.exc) { - frm.set_value("project_id", r.message.project_id); - frm.save(); - } - } + on_success: function ({ data }) { + frappe.show_alert({ + message: __("Firebase credentials uploaded successfully"), + indicator: "green", }); - } + frm.set_value("project_id", data.project_id); + if (frm.is_dirty()) { + // project id might be unchanged + frm.save(); + } else { + frm.refresh(); + } + }, }); }); - } + }, }); diff --git a/landa/water_body_management/doctype/firebase_settings/firebase_settings.py b/landa/water_body_management/doctype/firebase_settings/firebase_settings.py index fd555c7b..636d4d43 100644 --- a/landa/water_body_management/doctype/firebase_settings/firebase_settings.py +++ b/landa/water_body_management/doctype/firebase_settings/firebase_settings.py @@ -1,12 +1,12 @@ # Copyright (c) 2024, ALYF GmbH and contributors # For license information, please see license.txt import json -import os +from io import BytesIO +from pathlib import Path import frappe from frappe import _ from frappe.model.document import Document -from frappe.utils.file_manager import get_file class FirebaseSettings(Document): @@ -17,29 +17,43 @@ def validate(self): title=_("Missing Project ID"), ) + if self.enable_firebase_notifications and not self.has_credentials: + frappe.throw( + msg=_("Please upload the Credentials file."), + title=_("Missing Credentials"), + ) + + @property + def credentials_path(self): + return get_crendentials_path() + + @property + def has_credentials(self): + return self.credentials_path.exists() + + @frappe.whitelist() + def needs_credentials(self): + return not self.has_credentials + @frappe.whitelist() -def upload_api_file(file_url: str, file_id: str): - frappe.only_for("System Manager") +def upload_api_file(*args, **kwargs): + frappe.has_permission("Firebase Settings", "write", throw=True) - file_data = json.loads(get_file(file_url)[1]) - project_id = file_data.get("project_id") + json_data = json.load(BytesIO(frappe.local.uploaded_file)) + project_id = json_data.get("project_id") if not project_id: frappe.throw( msg=_("The uploaded file does not contain a project id."), title=_("Missing Project ID"), ) - # Write file contents to sites/sitename/firebase/firebase-credentials.json - folder_path = f"{frappe.local.site_path}/firebase" - if not os.path.exists(folder_path): - os.makedirs(folder_path) + credentials_path = get_crendentials_path() + credentials_path.parent.mkdir(exist_ok=True) + credentials_path.write_text(json.dumps(json_data, indent=1)) - with open(f"{folder_path}/credentials.json", "w") as f: - json.dump(file_data, f, indent=1) + return {"doctype": "File", "data": {"project_id": project_id}} - # Delete file, it was used temporarily. Hard to overwrite File uploader file creation action - frappe.delete_doc("File", file_id) - # Return project id for settings - return {"project_id": project_id} +def get_crendentials_path(): + return Path(frappe.local.site_path) / "firebase" / "credentials.json" diff --git a/landa/water_body_management/utils.py b/landa/water_body_management/utils.py index 9aa2e2b1..bdb530fd 100644 --- a/landa/water_body_management/utils.py +++ b/landa/water_body_management/utils.py @@ -38,9 +38,8 @@ def create_firebase_notification(doc, event): if not doc_eligible(doc): return - file_path = frappe.get_site_path("firebase/credentials.json") - enabled, topic, project_id = get_firebase_settings() - if not enabled: + firebase_settings = frappe.get_single("Firebase Settings") + if not firebase_settings.enable_firebase_notifications or not firebase_settings.has_credentials: return # doc must have keys same as `ChangeLog()._get_changed_data` query @@ -56,9 +55,9 @@ def create_firebase_notification(doc, event): frappe.enqueue( send_firebase_notification, queue="default", - file_path=file_path, - project_id=project_id, - topic=topic, + file_path=firebase_settings.credentials_path, + project_id=firebase_settings.project_id, + topic=firebase_settings.firebase_topic, change_log=change_log, now=frappe.conf.developer_mode, ) @@ -109,12 +108,3 @@ def format_doc_for_change_log(doc): doc.deleted = 1 return doc - - -def get_firebase_settings(): - """Get Firebase Settings""" - return frappe.get_cached_value( - "Firebase Settings", - None, - ["enable_firebase_notifications", "firebase_topic", "project_id"], - )