feat: Limit OAuth Client by roles
This commit is contained in:
parent
926c888374
commit
ae4eb87458
11 changed files with 95 additions and 8 deletions
|
|
@ -280,7 +280,7 @@ frappe.ui.form.on("User", {
|
||||||
frm.set_df_property("enabled", "read_only", 0);
|
frm.set_df_property("enabled", "read_only", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (frappe.session.user !== "Administrator") {
|
if (frm.doc.name !== "Administrator") {
|
||||||
frm.toggle_enable("email", frm.is_new());
|
frm.toggle_enable("email", frm.is_new());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -157,7 +157,7 @@ class User(Document):
|
||||||
self.password_strength_test()
|
self.password_strength_test()
|
||||||
|
|
||||||
if self.name not in STANDARD_USERS:
|
if self.name not in STANDARD_USERS:
|
||||||
self.validate_email_type(self.email)
|
self.email = self.name
|
||||||
self.validate_email_type(self.name)
|
self.validate_email_type(self.name)
|
||||||
self.add_system_manager_role()
|
self.add_system_manager_role()
|
||||||
self.move_role_profile_name_to_role_profiles()
|
self.move_role_profile_name_to_role_profiles()
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
"client_id",
|
"client_id",
|
||||||
"app_name",
|
"app_name",
|
||||||
"user",
|
"user",
|
||||||
|
"allowed_roles",
|
||||||
"cb_1",
|
"cb_1",
|
||||||
"client_secret",
|
"client_secret",
|
||||||
"skip_authorization",
|
"skip_authorization",
|
||||||
|
|
@ -114,10 +115,16 @@
|
||||||
"in_standard_filter": 1,
|
"in_standard_filter": 1,
|
||||||
"label": "Response Type",
|
"label": "Response Type",
|
||||||
"options": "Code\nToken"
|
"options": "Code\nToken"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "allowed_roles",
|
||||||
|
"fieldtype": "Table MultiSelect",
|
||||||
|
"label": "Allowed Roles",
|
||||||
|
"options": "OAuth Client Role"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2024-03-23 16:03:32.679227",
|
"modified": "2024-04-29 12:07:07.946980",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Integrations",
|
"module": "Integrations",
|
||||||
"name": "OAuth Client",
|
"name": "OAuth Client",
|
||||||
|
|
@ -141,4 +148,4 @@
|
||||||
"states": [],
|
"states": [],
|
||||||
"title_field": "app_name",
|
"title_field": "app_name",
|
||||||
"track_changes": 1
|
"track_changes": 1
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
import frappe
|
import frappe
|
||||||
from frappe import _
|
from frappe import _
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
|
from frappe.permissions import SYSTEM_USER_ROLE
|
||||||
|
|
||||||
|
|
||||||
class OAuthClient(Document):
|
class OAuthClient(Document):
|
||||||
|
|
@ -13,8 +14,10 @@ class OAuthClient(Document):
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
|
from frappe.integrations.doctype.oauth_client_role.oauth_client_role import OAuthClientRole
|
||||||
from frappe.types import DF
|
from frappe.types import DF
|
||||||
|
|
||||||
|
allowed_roles: DF.TableMultiSelect[OAuthClientRole]
|
||||||
app_name: DF.Data
|
app_name: DF.Data
|
||||||
client_id: DF.Data | None
|
client_id: DF.Data | None
|
||||||
client_secret: DF.Data | None
|
client_secret: DF.Data | None
|
||||||
|
|
@ -32,6 +35,7 @@ class OAuthClient(Document):
|
||||||
if not self.client_secret:
|
if not self.client_secret:
|
||||||
self.client_secret = frappe.generate_hash(length=10)
|
self.client_secret = frappe.generate_hash(length=10)
|
||||||
self.validate_grant_and_response()
|
self.validate_grant_and_response()
|
||||||
|
self.add_default_role()
|
||||||
|
|
||||||
def validate_grant_and_response(self):
|
def validate_grant_and_response(self):
|
||||||
if (
|
if (
|
||||||
|
|
@ -45,3 +49,12 @@ class OAuthClient(Document):
|
||||||
"Combination of Grant Type (<code>{0}</code>) and Response Type (<code>{1}</code>) not allowed"
|
"Combination of Grant Type (<code>{0}</code>) and Response Type (<code>{1}</code>) not allowed"
|
||||||
).format(self.grant_type, self.response_type)
|
).format(self.grant_type, self.response_type)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def add_default_role(self):
|
||||||
|
if not self.allowed_roles:
|
||||||
|
self.append("allowed_roles", {"role": SYSTEM_USER_ROLE})
|
||||||
|
|
||||||
|
def user_has_allowed_role(self) -> bool:
|
||||||
|
"""Returns true if session user is allowed to use this client."""
|
||||||
|
allowed_roles = {d.role for d in self.allowed_roles}
|
||||||
|
return bool(allowed_roles & set(frappe.get_roles()))
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
import frappe
|
||||||
|
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
"""Set default allowed role in OAuth Client"""
|
||||||
|
for client in frappe.get_all("OAuth Client", pluck="name"):
|
||||||
|
doc = frappe.get_doc("OAuth Client", client)
|
||||||
|
if doc.allowed_roles:
|
||||||
|
continue
|
||||||
|
row = doc.append("allowed_roles", {"role": "All"}) # Current default
|
||||||
|
row.db_insert()
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
{
|
||||||
|
"actions": [],
|
||||||
|
"creation": "2024-04-29 12:08:19.459404",
|
||||||
|
"doctype": "DocType",
|
||||||
|
"editable_grid": 1,
|
||||||
|
"engine": "InnoDB",
|
||||||
|
"field_order": [
|
||||||
|
"role"
|
||||||
|
],
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldname": "role",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Role",
|
||||||
|
"options": "Role"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"index_web_pages_for_search": 1,
|
||||||
|
"istable": 1,
|
||||||
|
"links": [],
|
||||||
|
"modified": "2024-04-29 12:16:48.018031",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "Integrations",
|
||||||
|
"name": "OAuth Client Role",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"permissions": [],
|
||||||
|
"sort_field": "creation",
|
||||||
|
"sort_order": "DESC",
|
||||||
|
"states": []
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
# Copyright (c) 2024, Frappe Technologies and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
# import frappe
|
||||||
|
from frappe.model.document import Document
|
||||||
|
|
||||||
|
|
||||||
|
class OAuthClientRole(Document):
|
||||||
|
# begin: auto-generated types
|
||||||
|
# This code is auto-generated. Do not modify anything in this block.
|
||||||
|
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from frappe.types import DF
|
||||||
|
|
||||||
|
parent: DF.Data
|
||||||
|
parentfield: DF.Data
|
||||||
|
parenttype: DF.Data
|
||||||
|
role: DF.Link | None
|
||||||
|
# end: auto-generated types
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
@ -20,10 +20,11 @@ class OAuthWebRequestValidator(RequestValidator):
|
||||||
# Simple validity check, does client exist? Not banned?
|
# Simple validity check, does client exist? Not banned?
|
||||||
cli_id = frappe.db.get_value("OAuth Client", {"name": client_id})
|
cli_id = frappe.db.get_value("OAuth Client", {"name": client_id})
|
||||||
if cli_id:
|
if cli_id:
|
||||||
request.client = frappe.get_doc("OAuth Client", client_id).as_dict()
|
client = frappe.get_doc("OAuth Client", client_id)
|
||||||
return True
|
if client.user_has_allowed_role():
|
||||||
else:
|
request.client = client.as_dict()
|
||||||
return False
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
def validate_redirect_uri(self, client_id, redirect_uri, request, *args, **kwargs):
|
def validate_redirect_uri(self, client_id, redirect_uri, request, *args, **kwargs):
|
||||||
# Is the client allowed to use the supplied redirect_uri? i.e. has
|
# Is the client allowed to use the supplied redirect_uri? i.e. has
|
||||||
|
|
|
||||||
|
|
@ -236,3 +236,4 @@ frappe.patches.v15_0.migrate_role_profile_to_table_multi_select
|
||||||
frappe.patches.v15_0.migrate_session_data
|
frappe.patches.v15_0.migrate_session_data
|
||||||
frappe.custom.doctype.property_setter.patches.remove_invalid_fetch_from_expressions
|
frappe.custom.doctype.property_setter.patches.remove_invalid_fetch_from_expressions
|
||||||
frappe.patches.v16_0.switch_default_sort_order
|
frappe.patches.v16_0.switch_default_sort_order
|
||||||
|
frappe.integrations.doctype.oauth_client.patches.set_default_allowed_role_in_oauth_client
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue