minor(ux): select field for alternating between basic and oauth authentication

This commit is contained in:
phot0n 2022-07-11 17:47:45 +05:30
parent 2907571098
commit 2b7bd4eef0
4 changed files with 45 additions and 31 deletions

View file

@ -93,6 +93,7 @@ frappe.ui.form.on("Email Account", {
});
}
frm.events.show_gmail_message_for_less_secure_apps(frm);
frm.events.toggle_auth_method(frm);
},
use_imap: function(frm) {
@ -134,6 +135,7 @@ frappe.ui.form.on("Email Account", {
frm.add_child("imap_folder", {"folder_name": "INBOX"});
frm.refresh_field("imap_folder");
}
frm.toggle_display(['auth_method'], frm.doc.service === "GMail");
},
refresh: function(frm) {
@ -150,11 +152,20 @@ frappe.ui.form.on("Email Account", {
},
after_save(frm) {
if (frm.doc.use_oauth && !frm.doc.refresh_token) {
if (frm.doc.auth_method === "Oauth" && !frm.doc.refresh_token) {
oauth_access(frm);
}
},
toggle_auth_method: function(frm) {
if (frm.doc.service !== "GMail") {
frm.toggle_display(['auth_method'], false);
frm.doc.auth_method = "Basic";
} else {
frm.toggle_display(['auth_method'], true);
}
},
show_gmail_message_for_less_secure_apps: function(frm) {
frm.dashboard.clear_headline();
let msg = __("GMail will only work if you enable 2-step authentication and use app-specific password OR use OAuth.");
@ -166,8 +177,8 @@ frappe.ui.form.on("Email Account", {
},
show_oauth_authorization_message(frm) {
let msg = __("Oauth Enabled but not Authorized. Please use `Authorize API Access` Button to do the same.");
if (frm.doc.use_oauth && !frm.doc.refresh_token) {
if (frm.doc.auth_method === "Oauth" && !frm.doc.refresh_token) {
let msg = __("Oauth Enabled but not Authorized. Please use Authorize API Access Button to do the same.");
frm.dashboard.clear_headline();
frm.dashboard.set_headline_alert(msg, "yellow");
}

View file

@ -14,12 +14,12 @@
"domain",
"service",
"authentication_column",
"auth_method",
"authorize_api_access",
"password",
"awaiting_password",
"ascii_encode_password",
"column_break_10",
"use_oauth",
"authorize_api_access",
"refresh_token",
"access_token",
"login_id_is_different",
@ -103,6 +103,7 @@
"label": "Email Login ID"
},
{
"depends_on": "eval: doc.auth_method === \"Basic\"",
"fieldname": "password",
"fieldtype": "Password",
"hide_days": 1,
@ -111,6 +112,7 @@
},
{
"default": "0",
"depends_on": "eval: doc.auth_method === \"Basic\"",
"fieldname": "awaiting_password",
"fieldtype": "Check",
"hide_days": 1,
@ -119,6 +121,7 @@
},
{
"default": "0",
"depends_on": "eval: doc.auth_method === \"Basic\"",
"fieldname": "ascii_encode_password",
"fieldtype": "Check",
"hide_days": 1,
@ -583,14 +586,7 @@
"label": "IMAP Details"
},
{
"default": "0",
"depends_on": "eval: doc.service === \"GMail\"",
"fieldname": "use_oauth",
"fieldtype": "Check",
"label": "Use OAuth"
},
{
"depends_on": "eval: doc.service === \"GMail\" && doc.use_oauth && !doc.__islocal && !doc.__unsaved",
"depends_on": "eval: doc.service === \"GMail\" && doc.auth_method === \"Oauth\" && !doc.__islocal && !doc.__unsaved",
"fieldname": "authorize_api_access",
"fieldtype": "Button",
"label": "Authorize API Access"
@ -608,12 +604,19 @@
"hidden": 1,
"label": "Access Token",
"read_only": 1
},
{
"default": "Basic",
"fieldname": "auth_method",
"fieldtype": "Select",
"label": "Method",
"options": "Basic\nOauth"
}
],
"icon": "fa fa-inbox",
"index_web_pages_for_search": 1,
"links": [],
"modified": "2022-07-11 15:11:15.196935",
"modified": "2022-07-11 17:29:13.651583",
"modified_by": "Administrator",
"module": "Email",
"name": "Email Account",

View file

@ -81,10 +81,13 @@ class EmailAccount(Document):
if frappe.local.flags.in_patch or frappe.local.flags.in_test:
return
if getattr(self, "service", "") != "GMail" and self.use_oauth:
self.use_oauth = 0
use_oauth = self.auth_method == "Oauth"
if self.use_oauth:
if getattr(self, "service", "") != "GMail" and use_oauth:
self.auth_method = "Basic"
use_oauth = False
if use_oauth:
# no need for awaiting password for oauth
self.awaiting_password = 0
@ -92,7 +95,7 @@ class EmailAccount(Document):
# clear access & refresh token
self.refresh_token = self.access_token = None
if not frappe.local.flags.in_install and (self.use_oauth or not self.awaiting_password):
if not frappe.local.flags.in_install and (use_oauth or not self.awaiting_password):
if self.refresh_token or self.password or self.smtp_server in ("127.0.0.1", "localhost"):
if self.enable_incoming:
self.get_incoming_server()
@ -102,7 +105,7 @@ class EmailAccount(Document):
self.validate_smtp_conn()
else:
if self.enable_incoming or (self.enable_outgoing and not self.no_smtp_authentication):
if not self.use_oauth:
if not use_oauth:
frappe.throw(_("Password is required or select Awaiting Password"))
if self.notify_if_unreplied:
@ -155,7 +158,7 @@ class EmailAccount(Document):
awaiting_password=self.awaiting_password,
email_id=self.email_id,
enable_outgoing=self.enable_outgoing,
used_oauth=self.use_oauth,
used_oauth=self.auth_method == "Oauth",
)
def there_must_be_only_one_default(self):
@ -210,7 +213,7 @@ class EmailAccount(Document):
"email_sync_rule": email_sync_rule,
"incoming_port": get_port(self),
"initial_sync_count": self.initial_sync_count or 100,
"use_oauth": self.use_oauth or 0,
"use_oauth": self.auth_method == "Oauth",
"refresh_token": decrypt(self.refresh_token) if self.refresh_token else None,
"access_token": decrypt(self.access_token) if self.access_token else None,
}
@ -279,7 +282,9 @@ class EmailAccount(Document):
@property
def _password(self):
raise_exception = not (self.use_oauth or self.no_smtp_authentication or frappe.flags.in_test)
raise_exception = not (
self.auth_method == "Oauth" or self.no_smtp_authentication or frappe.flags.in_test
)
return self.get_password(raise_exception=raise_exception)
@property
@ -398,7 +403,7 @@ class EmailAccount(Document):
"default": 0,
},
"name": {"conf_names": ("email_sender_name",), "default": "Frappe"},
"use_oauth": {"conf_names": ("use_oauth"), "default": 0},
"auth_method": {"conf_names": ("auth_method"), "default": "Basic"},
"access_token": {"conf_names": ("mail_access_token")},
"refresh_token": {"conf_names": ("mail_refresh_token")},
"from_site_config": {"default": True},
@ -426,7 +431,7 @@ class EmailAccount(Document):
"use_ssl": cint(self.use_ssl_for_outgoing),
"use_tls": cint(self.use_tls),
"service": getattr(self, "service", ""),
"use_oauth": self.use_oauth or 0,
"use_oauth": self.auth_method == "Oauth",
"refresh_token": decrypt(self.refresh_token) if self.refresh_token else None,
"access_token": decrypt(self.access_token) if self.access_token else None,
}
@ -800,7 +805,7 @@ def pull(now=False):
for email_account in frappe.get_list(
"Email Account",
filters={"enable_incoming": 1},
or_filters={"awaiting_password": 0, "use_oauth": 1},
or_filters={"awaiting_password": 0, "auth_method": "Oauth"},
):
if now:
pull_from_email_account(email_account.name)
@ -923,7 +928,7 @@ def remove_user_email_inbox(email_account):
@frappe.whitelist()
def set_email_password(email_account, password):
account = frappe.get_doc("Email Account", email_account)
if account.awaiting_password and not account.use_oauth:
if account.awaiting_password and not account.auth_method == "Oauth":
account.awaiting_password = 0
account.password = password
try:

View file

@ -2,7 +2,6 @@ import base64
from imaplib import IMAP4
from poplib import POP3
from smtplib import SMTP
from typing import Union
from urllib.parse import quote
import frappe
@ -124,10 +123,6 @@ def oauth_access(email_account: str, service: str):
doctype = "Email Account"
# NOTE: setting this here, since we redirect to the service's auth page,
# we lose the use_oauth value in the emal account form
frappe.db.set_value(doctype, email_account, "use_oauth", 1, update_modified=False)
if service == "GMail":
return authorize_google_access(email_account, doctype)