Social login refactor (#4519)
* Added DocType Social Login Key WIP for https://github.com/frappe/frappe/issues/4496 added basic fields after_insert add provider_username and provider_userid fields on User dt on_trash deletes added fields on User dt * Added field to store fontawesome icon for provider * [Patch] Social Login Keys to Social Login Key * [Patch] Social Login Keys to Social Login Key * Social Login Key generates boilerplate * patch fixed for social_login_refactor * removed patch-not working * use social login keys to initiate flow * Login page shows Social Login Key * show login via if base_url present * removed boilerplate generator * Multiple Changes fix zxcvbn import in password_strength.py use of child table instead of additional fields on user dt to store username and userid * Fetched Template on Client JS * Frappe social login template working * Added Social Login Key Templates * Codacy fixes and validate social login key urls * [Patch] Social Login Keys (untested) * [Fix] Patch refactor social login keys * [Fix] Patch refactor_social_login_keys manually tested * Refactor OAuth 2.0 related changes for Social Login Key * [Fix] Patch refactor social login keys * Test - Adding Frappe Social Login Key * Social Login Key Tests check added child table entry on user for provider frappe it also checks if userid is created * [WIP] Office 365 Social Login Key Template * [Fix] Social Login - Redirect URL * [Test] Single sign-on icons for added provider * [Fix] Codacy Errors * [Fix] Social Login Key Form JS * Docs Added for Social Login Key * [Fix] Patch Refactor Social Login Keys * Handle different icon types Handle different icon types (image, icon, emoji) with just icon field * Move the login methods to a new py file frappe.integrations.oauth2_logins added copied whitelisted guest oauth2 redirect endpoints from login.py removing the functions from login.py will break backward compatibility * Social Login Key Form Changes Moved Enable field to top Fields which are not editable are collapsed * [Fix] Codacy Errors * Corrected Docs, sync.py * [Docs] Adding a social login provider * [Fix] set frappe userid from User Social Login * [Fix] frappe userid in oauth.py * removed icon_type * Use frappe.utils.is_image
This commit is contained in:
parent
ba9f53bcce
commit
02aa7b6f41
35 changed files with 1555 additions and 776 deletions
|
|
@ -44,7 +44,7 @@ def get_data():
|
|||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Social Login Keys",
|
||||
"name": "Social Login Key",
|
||||
"description": _("Enter keys to enable login via Facebook, Google, GitHub."),
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -26,6 +26,10 @@ class TestUser(unittest.TestCase):
|
|||
first_name='Tester')).insert()
|
||||
self.assertEquals(new_user.user_type, 'Website User')
|
||||
|
||||
# social login userid for frappe
|
||||
self.assertTrue(new_user.social_logins[0].userid)
|
||||
self.assertEquals(new_user.social_logins[0].provider, "frappe")
|
||||
|
||||
# role with desk access
|
||||
new_user.add_roles('_Test Role 2')
|
||||
new_user.save()
|
||||
|
|
|
|||
|
|
@ -1851,95 +1851,8 @@
|
|||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "fb_username",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Facebook Username",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "fb_userid",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Facebook User ID",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "google_userid",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Google User ID",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_49",
|
||||
"fieldtype": "Column Break",
|
||||
"fieldname": "social_logins",
|
||||
"fieldtype": "Table",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
|
|
@ -1947,8 +1860,10 @@
|
|||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Social Logins",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "User Social Login",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
|
|
@ -1961,94 +1876,6 @@
|
|||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "github_userid",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Github User ID",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "github_username",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Github Username",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "frappe_userid",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Frappe User ID",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
|
|
@ -2124,7 +1951,7 @@
|
|||
"istable": 0,
|
||||
"max_attachments": 5,
|
||||
"menu_index": 0,
|
||||
"modified": "2017-11-15 13:01:00.085916",
|
||||
"modified": "2017-12-29 14:37:57.759229",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Core",
|
||||
"name": "User",
|
||||
|
|
|
|||
|
|
@ -75,8 +75,8 @@ class User(Document):
|
|||
if self.language == "Loading...":
|
||||
self.language = None
|
||||
|
||||
if (self.name not in ["Administrator", "Guest"]) and (not self.frappe_userid):
|
||||
self.frappe_userid = frappe.generate_hash(length=39)
|
||||
if (self.name not in ["Administrator", "Guest"]) and (not self.get_social_login_userid("frappe")):
|
||||
self.set_social_login_userid("frappe", frappe.generate_hash(length=39))
|
||||
|
||||
def validate_roles(self):
|
||||
if self.role_profile_name:
|
||||
|
|
@ -494,6 +494,25 @@ class User(Document):
|
|||
if len(email_accounts) != len(set(email_accounts)):
|
||||
frappe.throw(_("Email Account added multiple times"))
|
||||
|
||||
def get_social_login_userid(self, provider):
|
||||
try:
|
||||
for p in self.social_logins:
|
||||
if p.provider == provider:
|
||||
return p.userid
|
||||
except:
|
||||
return None
|
||||
|
||||
def set_social_login_userid(self, provider, userid, username=None):
|
||||
social_logins = {
|
||||
"provider": provider,
|
||||
"userid": userid
|
||||
}
|
||||
|
||||
if username:
|
||||
social_logins["username"] = username
|
||||
|
||||
self.append("social_logins", social_logins)
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_timezones():
|
||||
import pytz
|
||||
|
|
|
|||
189
frappe/core/doctype/user_social_login/user_social_login.json
Normal file
189
frappe/core/doctype/user_social_login/user_social_login.json
Normal file
|
|
@ -0,0 +1,189 @@
|
|||
{
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
"creation": "2017-12-02 13:01:20.507112",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "provider",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Provider",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "section_break_0",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "username",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Username",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_0",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "userid",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "User ID",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-12-02 15:37:58.397062",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Core",
|
||||
"name": "User Social Login",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2017, Frappe Technologies and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
from frappe.model.document import Document
|
||||
|
||||
class UserSocialLogin(Document):
|
||||
pass
|
||||
BIN
frappe/docs/assets/img/social_login_key.png
Normal file
BIN
frappe/docs/assets/img/social_login_key.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 72 KiB |
|
|
@ -0,0 +1,49 @@
|
|||
# Adding Social Login Provider
|
||||
|
||||
This guide discusses how to add a social login provider to frappe via pull request.
|
||||
|
||||
### Add your provider in `SocialLoginKey.get_social_login_provider`
|
||||
|
||||
```
|
||||
providers["Frappe"] = {
|
||||
"provider_name": "Frappe",
|
||||
"enable_social_login": 1,
|
||||
"custom_base_url": 1,
|
||||
"icon":"/assets/frappe/images/favicon.png",
|
||||
"redirect_url": "/api/method/frappe.www.login.login_via_frappe",
|
||||
"api_endpoint": "/api/method/frappe.integrations.oauth2.openid_profile",
|
||||
"api_endpoint_args":None,
|
||||
"authorize_url": "/api/method/frappe.integrations.oauth2.authorize",
|
||||
"access_token_url": "/api/method/frappe.integrations.oauth2.get_token",
|
||||
"auth_url_data": json.dumps({
|
||||
"response_type": "code",
|
||||
"scope": "openid"
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
### Add provider key in exact same type case in options of `social_login_provider` select field on `Social Login Key` DocType. e.g. `Frappe`
|
||||
|
||||
Once the user adds a social login provider and enables it the `Authorization Code` is sent back by the provider api server on to the redirect_url mentioned on the same server. You will have to add a whitelisted method allowing guest access in `frappe.integrations.oauth2_logins`. e.g. `login_via_office365`
|
||||
|
||||
There many implementations of OAuth 2.0 + OpenID Connect. Here we'll discuss two ways of accessing openid information.
|
||||
|
||||
#### User Creation via OpenID Profile Endpoint
|
||||
|
||||
example:
|
||||
|
||||
```
|
||||
@frappe.whitelist(allow_guest=True)
|
||||
def login_via_frappe(code, state):
|
||||
login_via_oauth2("frappe", code, state, decoder=json.loads)
|
||||
```
|
||||
|
||||
#### User Creation via id_token
|
||||
|
||||
example:
|
||||
|
||||
```
|
||||
@frappe.whitelist(allow_guest=True)
|
||||
def login_via_office365(code, state):
|
||||
login_via_oauth2_id_token("office_365", code, state, decoder=json.loads)
|
||||
```
|
||||
|
|
@ -13,3 +13,4 @@ single-type-doctype
|
|||
trigger-event-on-deletion-of-grid-row
|
||||
dialogs-types
|
||||
using-html-templates-in-javascript
|
||||
adding-social-login-provider
|
||||
|
|
|
|||
|
|
@ -63,4 +63,20 @@ To enable these signups, you need to have **Client ID** and **Client Secret** fr
|
|||
<iframe src="https://www.youtube.com/embed/bG71DxxkVjQ" class="embed-responsive-item" allowfullscreen></iframe>
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
### Office 365
|
||||
|
||||
1. Go to [https://portal.azure.com](https://portal.azure.com)
|
||||
1. Create a new Azure Active Directory > App Registration.
|
||||
1. Click on New Application Registration
|
||||
1. Fill the form with:
|
||||
- Application Name
|
||||
- Application Type - Web app / API
|
||||
- Single Sign-on URL as
|
||||
**http://{{ yoursite }}/api/method/frappe.www.login.login\_via\_office365**
|
||||
1. Enable Multi Tenent for the added App.
|
||||
1. Go to the section **Application ID** and copy the Client ID and copy Client Secret by adding new password into Social Login Key
|
||||
|
||||
---
|
||||
<!-- markdown -->
|
||||
|
|
|
|||
|
|
@ -3,3 +3,4 @@ how_to_setup_oauth
|
|||
using_oauth
|
||||
openid_connect_and_frappe_social_login
|
||||
google_gsuite
|
||||
social_login_key
|
||||
|
|
|
|||
26
frappe/docs/user/en/guides/integration/social_login_key.md
Normal file
26
frappe/docs/user/en/guides/integration/social_login_key.md
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
# Social Login Key
|
||||
|
||||
Add social login providers like Facebook, Frappe, Github, Google, Microsoft, etc and enable social login.
|
||||
|
||||
#### Setup Social Logins
|
||||
|
||||
To add Social Login Key go to
|
||||
|
||||
> Integrations > Authentication > Social Login Key
|
||||
|
||||
Social Login Key
|
||||
|
||||
<img class="screenshot" src="/docs/assets/img/social_login_key.png">
|
||||
|
||||
1. Select the Social Login Provider or select "Custom"
|
||||
2. If required for provider enter "Base URL"
|
||||
3. To enable check "Enable Social Login" to show Icon on login screen
|
||||
4. Also add Client ID and Client Secret as per provider.
|
||||
|
||||
e.g. Social Login Key
|
||||
|
||||
- **Social Login Provider** : `Frappe`
|
||||
- **Client ID** : `ABCDEFG`
|
||||
- **Client Secret** : `123456`
|
||||
- **Enable Social Login** : `Check`
|
||||
- **Base URL** : `https://erpnext.org` (required for some providers)
|
||||
0
frappe/integrations/doctype/social_login_key/__init__.py
Normal file
0
frappe/integrations/doctype/social_login_key/__init__.py
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
// Copyright (c) 2017, Frappe Technologies and contributors
|
||||
// For license information, please see license.txt
|
||||
const fields = [
|
||||
"provider_name", "base_url", "custom_base_url",
|
||||
"icon", "authorize_url", "access_token_url", "redirect_url",
|
||||
"api_endpoint", "api_endpoint_args", "auth_url_data"
|
||||
];
|
||||
|
||||
frappe.ui.form.on('Social Login Key', {
|
||||
refresh(frm) {
|
||||
frm.trigger("setup_fields");
|
||||
},
|
||||
|
||||
custom_base_url(frm) {
|
||||
frm.trigger("setup_fields");
|
||||
},
|
||||
|
||||
social_login_provider(frm) {
|
||||
if(frm.doc.social_login_provider != "Custom") {
|
||||
frappe.call({
|
||||
"doc": frm.doc,
|
||||
"method": "get_social_login_provider",
|
||||
"args": {
|
||||
"provider": frm.doc.social_login_provider
|
||||
}
|
||||
}).done((r) => {
|
||||
const provider = r.message;
|
||||
for(var field of fields) {
|
||||
frm.set_value(field, provider[field]);
|
||||
frm.set_df_property(field, "read_only", 1);
|
||||
if (frm.doc.custom_base_url) {
|
||||
frm.toggle_enable("base_url", 1);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
frm.trigger("clear_fields");
|
||||
frm.trigger("setup_fields");
|
||||
}
|
||||
},
|
||||
|
||||
setup_fields(frm) {
|
||||
// set custom_base_url to read only for "Custom" provider
|
||||
if(frm.doc.social_login_provider == "Custom") {
|
||||
frm.set_value("custom_base_url", 1);
|
||||
frm.set_df_property("custom_base_url", "read_only", 1);
|
||||
}
|
||||
|
||||
// set fields to read only for providers from template
|
||||
for(var f of fields) {
|
||||
if(frm.doc.social_login_provider != "Custom"){
|
||||
frm.set_df_property(f, "read_only", 1);
|
||||
}
|
||||
}
|
||||
|
||||
// enable base_url for providers with custom_base_url
|
||||
if(frm.doc.custom_base_url) {
|
||||
frm.set_df_property("base_url", "read_only", 0);
|
||||
frm.fields_dict["sb_identity_details"].collapse(false);
|
||||
}
|
||||
|
||||
// hide social_login_provider and provider_name for non local
|
||||
if(!frm.doc.__islocal &&
|
||||
(frm.doc.social_login_provider ||
|
||||
frm.doc.provider_name)) {
|
||||
frm.set_df_property("social_login_provider", "hidden", 1);
|
||||
frm.set_df_property("provider_name", "hidden", 1);
|
||||
}
|
||||
},
|
||||
|
||||
clear_fields(frm) {
|
||||
for(var field of fields){
|
||||
frm.set_value(field, "");
|
||||
frm.set_df_property(field, "read_only", 0);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
|
@ -0,0 +1,700 @@
|
|||
{
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 1,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
"creation": "2017-11-18 15:36:09.676722",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Document",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "enable_social_login",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Enable Social Login",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 1,
|
||||
"collapsible_depends_on": "eval:doc.enable_social_login",
|
||||
"columns": 0,
|
||||
"fieldname": "client_credentials",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Client Credentials",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "Custom",
|
||||
"depends_on": "eval:doc.custom!=1",
|
||||
"fieldname": "social_login_provider",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Social Login Provider",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Custom\nFacebook\nFrappe\nGitHub\nGoogle\nOffice 365",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 1,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "client_id",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Client ID",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_0",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "provider_name",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Provider Name",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 1,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "client_secret",
|
||||
"fieldtype": "Password",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Client Secret",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 1,
|
||||
"collapsible_depends_on": "eval:doc.custom_base_url",
|
||||
"columns": 0,
|
||||
"depends_on": "",
|
||||
"fieldname": "sb_identity_details",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Identity Details",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "icon",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Icon",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_1",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "base_url",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Base URL",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 1,
|
||||
"collapsible_depends_on": "eval:doc.social_login_provider===\"Custom\"",
|
||||
"columns": 0,
|
||||
"depends_on": "",
|
||||
"fieldname": "client_urls",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Client URLs",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "authorize_url",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Authorize URL",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "access_token_url",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Access Token URL",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_3",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "redirect_url",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Redirect URL",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "api_endpoint",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "API Endpoint",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "custom_base_url",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Custom Base URL",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 1,
|
||||
"collapsible_depends_on": "eval:doc.social_login_provider===\"Custom\"",
|
||||
"columns": 0,
|
||||
"depends_on": "",
|
||||
"fieldname": "client_information",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Client Information",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "api_endpoint_args",
|
||||
"fieldtype": "Code",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "API Endpoint Args",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "auth_url_data",
|
||||
"fieldtype": "Code",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Auth URL Data",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-12-21 13:55:17.041059",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Integrations",
|
||||
"name": "Social Login Key",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"title_field": "provider_name",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0
|
||||
}
|
||||
130
frappe/integrations/doctype/social_login_key/social_login_key.py
Normal file
130
frappe/integrations/doctype/social_login_key/social_login_key.py
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2017, Frappe Technologies and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe, json
|
||||
from frappe import _
|
||||
from frappe.model.document import Document
|
||||
|
||||
class BaseUrlNotSetError(frappe.ValidationError): pass
|
||||
class AuthorizeUrlNotSetError(frappe.ValidationError): pass
|
||||
class AccessTokenUrlNotSetError(frappe.ValidationError): pass
|
||||
class RedirectUrlNotSetError(frappe.ValidationError): pass
|
||||
class ClientIDNotSetError(frappe.ValidationError): pass
|
||||
class ClientSecretNotSetError(frappe.ValidationError): pass
|
||||
|
||||
class SocialLoginKey(Document):
|
||||
|
||||
def autoname(self):
|
||||
self.name = frappe.scrub(self.provider_name)
|
||||
|
||||
def validate(self):
|
||||
if self.custom_base_url and not self.base_url:
|
||||
frappe.throw(_("Please enter Base URL"), exc=BaseUrlNotSetError)
|
||||
if not self.authorize_url:
|
||||
frappe.throw(_("Please enter Authorize URL"), exc=AuthorizeUrlNotSetError)
|
||||
if not self.access_token_url:
|
||||
frappe.throw(_("Please enter Access Token URL"), exc=AccessTokenUrlNotSetError)
|
||||
if not self.redirect_url:
|
||||
frappe.throw(_("Please enter Redirect URL"), exc=RedirectUrlNotSetError)
|
||||
if self.enable_social_login and not self.client_id:
|
||||
frappe.throw(_("Please enter Client ID before social login is enabled"), exc=ClientIDNotSetError)
|
||||
if self.enable_social_login and not self.client_secret:
|
||||
frappe.throw(_("Please enter Client Secret before social login is enabled"), exc=ClientSecretNotSetError)
|
||||
|
||||
def get_social_login_provider(self, provider, initialize=False):
|
||||
providers = {}
|
||||
|
||||
providers["Office 365"] = {
|
||||
"provider_name": "Office 365",
|
||||
"enable_social_login": 1,
|
||||
"base_url": "https://login.microsoftonline.com",
|
||||
"custom_base_url": 0,
|
||||
"icon":"fa fa-windows",
|
||||
"authorize_url": "https://login.microsoftonline.com/common/oauth2/authorize",
|
||||
"access_token_url": "https://login.microsoftonline.com/common/oauth2/token",
|
||||
"redirect_url": "/api/method/frappe.integrations.oauth2_logins.login_via_office365",
|
||||
"api_endpoint": None,
|
||||
"api_endpoint_args":None,
|
||||
"auth_url_data": json.dumps({
|
||||
"response_type": "code",
|
||||
"scope":"openid"
|
||||
})
|
||||
}
|
||||
|
||||
providers["GitHub"] = {
|
||||
"provider_name":"GitHub",
|
||||
"enable_social_login": 1,
|
||||
"base_url":"https://api.github.com/",
|
||||
"custom_base_url":0,
|
||||
"icon":"fa fa-github",
|
||||
"authorize_url":"https://github.com/login/oauth/authorize",
|
||||
"access_token_url":"https://github.com/login/oauth/access_token",
|
||||
"redirect_url":"/api/method/frappe.www.login.login_via_github",
|
||||
"api_endpoint":"user",
|
||||
"api_endpoint_args":None,
|
||||
"auth_url_data":None
|
||||
}
|
||||
|
||||
providers["Google"] = {
|
||||
"provider_name": "Google",
|
||||
"enable_social_login": 1,
|
||||
"base_url": "https://www.googleapis.com",
|
||||
"custom_base_url": 0,
|
||||
"icon":"fa fa-google",
|
||||
"authorize_url": "https://accounts.google.com/o/oauth2/auth",
|
||||
"access_token_url": "https://accounts.google.com/o/oauth2/token",
|
||||
"redirect_url": "/api/method/frappe.www.login.login_via_google",
|
||||
"api_endpoint": "oauth2/v2/userinfo",
|
||||
"api_endpoint_args":None,
|
||||
"auth_url_data": json.dumps({
|
||||
"scope": "https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email",
|
||||
"response_type": "code"
|
||||
})
|
||||
}
|
||||
|
||||
providers["Facebook"] = {
|
||||
"provider_name": "Facebook",
|
||||
"enable_social_login": 1,
|
||||
"base_url": "https://graph.facebook.com",
|
||||
"custom_base_url": 0,
|
||||
"icon": "fa fa-facebook",
|
||||
"authorize_url": "https://www.facebook.com/dialog/oauth",
|
||||
"access_token_url": "https://graph.facebook.com/oauth/access_token",
|
||||
"redirect_url": "/api/method/frappe.www.login.login_via_facebook",
|
||||
"api_endpoint": "/v2.5/me",
|
||||
"api_endpoint_args": json.dumps({
|
||||
"fields": "first_name,last_name,email,gender,location,verified,picture"
|
||||
}),
|
||||
"auth_url_data": json.dumps({
|
||||
"display": "page",
|
||||
"response_type": "code",
|
||||
"scope": "email,public_profile"
|
||||
})
|
||||
}
|
||||
|
||||
providers["Frappe"] = {
|
||||
"provider_name": "Frappe",
|
||||
"enable_social_login": 1,
|
||||
"custom_base_url": 1,
|
||||
"icon":"/assets/frappe/images/favicon.png",
|
||||
"redirect_url": "/api/method/frappe.www.login.login_via_frappe",
|
||||
"api_endpoint": "/api/method/frappe.integrations.oauth2.openid_profile",
|
||||
"api_endpoint_args":None,
|
||||
"authorize_url": "/api/method/frappe.integrations.oauth2.authorize",
|
||||
"access_token_url": "/api/method/frappe.integrations.oauth2.get_token",
|
||||
"auth_url_data": json.dumps({
|
||||
"response_type": "code",
|
||||
"scope": "openid"
|
||||
})
|
||||
}
|
||||
|
||||
# Initialize the doc and return, used in patch
|
||||
# Or can be used for creating key from controller
|
||||
if initialize and provider:
|
||||
for k, v in providers[provider].items():
|
||||
setattr(self,k,v)
|
||||
return
|
||||
|
||||
return providers.get(provider) if provider else providers
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Social Login Key", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Social Login Key
|
||||
() => frappe.tests.make('Social Login Key', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2017, Frappe Technologies and Contributors
|
||||
# See license.txt
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
from frappe.integrations.doctype.social_login_key.social_login_key import BaseUrlNotSetError
|
||||
import unittest
|
||||
|
||||
class TestSocialLoginKey(unittest.TestCase):
|
||||
def test_adding_frappe_social_login_provider(self):
|
||||
provider_name = "Frappe"
|
||||
social_login_key = make_social_login_key(
|
||||
social_login_provider=provider_name
|
||||
)
|
||||
social_login_key.get_social_login_provider(provider_name, initialize=True)
|
||||
self.assertRaises(BaseUrlNotSetError, social_login_key.insert)
|
||||
|
||||
def make_social_login_key(**kwargs):
|
||||
kwargs["doctype"] = "Social Login Key"
|
||||
if not "provider_name" in kwargs:
|
||||
kwargs["provider_name"] = "Test OAuth2 Provider"
|
||||
doc = frappe.get_doc(kwargs)
|
||||
return doc
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
// Copyright (c) 2016, Frappe Technologies and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Social Login Keys', {
|
||||
refresh: function(frm) {
|
||||
|
||||
}
|
||||
});
|
||||
|
|
@ -1,414 +0,0 @@
|
|||
{
|
||||
"allow_copy": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
"creation": "2014-03-04 08:29:52",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "System",
|
||||
"editable_grid": 0,
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "facebook",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Facebook",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "facebook_client_id",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Facebook Client ID",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "facebook_client_secret",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Facebook Client Secret",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "google",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Google",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "google_client_id",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Google Client ID",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "google_client_secret",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Google Client Secret",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "github",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "GitHub",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "github_client_id",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "GitHub Client ID",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "github_client_secret",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "GitHub Client Secret",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "frappe",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Frappe",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "frappe_client_id",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Frappe Client ID",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "frappe_client_secret",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Frappe Client Secret",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "frappe_server_url",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Frappe Server URL",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"icon": "icon-signin",
|
||||
"idx": 1,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"in_dialog": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 1,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-12-29 14:40:30.397643",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Integrations",
|
||||
"name": "Social Login Keys",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 0,
|
||||
"email": 0,
|
||||
"export": 0,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"is_custom": 0,
|
||||
"permlevel": 0,
|
||||
"print": 0,
|
||||
"read": 1,
|
||||
"report": 0,
|
||||
"role": "System Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"sort_order": "ASC",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# MIT License. See license.txt
|
||||
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
import requests
|
||||
import socket
|
||||
|
||||
from frappe.model.document import Document
|
||||
from frappe import _
|
||||
from six.moves.urllib.parse import urlparse
|
||||
|
||||
class SocialLoginKeys(Document):
|
||||
def validate(self):
|
||||
self.validate_frappe_server_url()
|
||||
|
||||
def validate_frappe_server_url(self):
|
||||
if self.frappe_server_url:
|
||||
if self.frappe_server_url.endswith('/'):
|
||||
self.frappe_server_url = self.frappe_server_url[:-1]
|
||||
|
||||
try:
|
||||
frappe_server_hostname = urlparse(self.frappe_server_url).netloc
|
||||
except:
|
||||
frappe.throw(_("Check Frappe Server URL"))
|
||||
|
||||
if socket.gethostname() != frappe_server_hostname or \
|
||||
(frappe.local.conf.domains is not None) and \
|
||||
(frappe_server_hostname not in frappe.local.conf.domains):
|
||||
try:
|
||||
requests.get(self.frappe_server_url + "/api/method/frappe.handler.version", timeout=5)
|
||||
except:
|
||||
frappe.throw(_("Unable to make request to the Frappe Server URL"))
|
||||
|
|
@ -103,9 +103,9 @@ def get_token(*args, **kwargs):
|
|||
headers = r.headers
|
||||
|
||||
#Check whether frappe server URL is set
|
||||
frappe_server_url = frappe.db.get_value("Social Login Keys", None, "frappe_server_url") or None
|
||||
frappe_server_url = frappe.db.get_value("Social Login Key", "frappe", "base_url") or None
|
||||
if not frappe_server_url:
|
||||
frappe.throw(_("Define Frappe Server URL in Social Login Keys"))
|
||||
frappe.throw(_("Please set Base URL in Social Login Key for Frappe"))
|
||||
|
||||
try:
|
||||
headers, body, status = get_oauth_server().create_token_response(uri, http_method, body, headers, frappe.flags.oauth_credentials)
|
||||
|
|
@ -124,7 +124,7 @@ def get_token(*args, **kwargs):
|
|||
id_token = {
|
||||
"aud": token_client,
|
||||
"exp": int((frappe.db.get_value("OAuth Bearer Token", out.access_token, "expiration_time") - frappe.utils.datetime.datetime(1970, 1, 1)).total_seconds()),
|
||||
"sub": frappe.db.get_value("User", token_user, "frappe_userid"),
|
||||
"sub": frappe.db.get_value("User Social Login", {"parent":token_user, "provider": "frappe"}, "userid"),
|
||||
"iss": frappe_server_url,
|
||||
"at_hash": frappe.oauth.calculate_at_hash(out.access_token, hashlib.sha256)
|
||||
}
|
||||
|
|
@ -156,7 +156,8 @@ def revoke_token(*args, **kwargs):
|
|||
@frappe.whitelist()
|
||||
def openid_profile(*args, **kwargs):
|
||||
picture = None
|
||||
first_name, last_name, avatar, name, frappe_userid = frappe.db.get_value("User", frappe.session.user, ["first_name", "last_name", "user_image", "name", "frappe_userid"])
|
||||
first_name, last_name, avatar, name = frappe.db.get_value("User", frappe.session.user, ["first_name", "last_name", "user_image", "name"])
|
||||
frappe_userid = frappe.db.get_value("User Social Login", {"parent":frappe.session.user, "provider": "frappe"}, "userid")
|
||||
request_url = urlparse(frappe.request.url)
|
||||
|
||||
if avatar:
|
||||
|
|
|
|||
28
frappe/integrations/oauth2_logins.py
Normal file
28
frappe/integrations/oauth2_logins.py
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# MIT License. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
import frappe.utils
|
||||
from frappe.utils.oauth import login_via_oauth2, login_via_oauth2_id_token
|
||||
import json
|
||||
|
||||
@frappe.whitelist(allow_guest=True)
|
||||
def login_via_google(code, state):
|
||||
login_via_oauth2("google", code, state, decoder=json.loads)
|
||||
|
||||
@frappe.whitelist(allow_guest=True)
|
||||
def login_via_github(code, state):
|
||||
login_via_oauth2("github", code, state)
|
||||
|
||||
@frappe.whitelist(allow_guest=True)
|
||||
def login_via_facebook(code, state):
|
||||
login_via_oauth2("facebook", code, state, decoder=json.loads)
|
||||
|
||||
@frappe.whitelist(allow_guest=True)
|
||||
def login_via_frappe(code, state):
|
||||
login_via_oauth2("frappe", code, state, decoder=json.loads)
|
||||
|
||||
@frappe.whitelist(allow_guest=True)
|
||||
def login_via_office365(code, state):
|
||||
login_via_oauth2_id_token("office_365", code, state, decoder=json.loads)
|
||||
|
|
@ -387,7 +387,7 @@ class OAuthWebRequestValidator(RequestValidator):
|
|||
- OpenIDConnectImplicit
|
||||
- OpenIDConnectHybrid
|
||||
"""
|
||||
if id_token_hint and id_token_hint == frappe.get_value("User", frappe.session.user, "frappe_userid"):
|
||||
if id_token_hint and id_token_hint == frappe.db.get_value("User Social Login", {"parent":frappe.session.user, "provider": "frappe"}, "userid"):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
|
|
|||
|
|
@ -200,4 +200,5 @@ frappe.patches.v9_1.resave_domain_settings
|
|||
frappe.patches.v9_1.revert_domain_settings
|
||||
frappe.patches.v9_1.move_feed_to_activity_log
|
||||
execute:frappe.delete_doc('Page', 'data-import-tool', ignore_missing=True)
|
||||
frappe.patches.v10_0.reload_countries_and_currencies
|
||||
frappe.patches.v10_0.reload_countries_and_currencies
|
||||
frappe.patches.v10_0.refactor_social_login_keys
|
||||
|
|
|
|||
91
frappe/patches/v10_0/refactor_social_login_keys.py
Normal file
91
frappe/patches/v10_0/refactor_social_login_keys.py
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
# see license
|
||||
import frappe
|
||||
|
||||
def execute():
|
||||
# Move User Data into DocType
|
||||
frappe.reload_doc("core", "doctype", "user", force=True)
|
||||
frappe.reload_doc("core", "doctype", "user_social_login", force=True)
|
||||
users = frappe.get_all("User", filters=[["username", "not in", ["Guest","Administrator"]]])
|
||||
for u in users:
|
||||
user = frappe.get_doc("User", u.get("name"))
|
||||
save = False
|
||||
|
||||
if user.fb_userid and user.fb_username:
|
||||
user.append("social_logins", {
|
||||
"provider": "facebook",
|
||||
"userid": user.fb_userid,
|
||||
"username": user.fb_username
|
||||
})
|
||||
save = True
|
||||
|
||||
if user.frappe_userid:
|
||||
user.append("social_logins", {
|
||||
"provider": "frappe",
|
||||
"userid": user.frappe_userid
|
||||
})
|
||||
save = True
|
||||
|
||||
if user.github_userid and user.github_username:
|
||||
user.append("social_logins", {
|
||||
"provider": "github",
|
||||
"userid": user.github_userid,
|
||||
"username": user.github_username,
|
||||
})
|
||||
save = True
|
||||
|
||||
if user.google_userid:
|
||||
user.append("social_logins", {
|
||||
"provider": "google",
|
||||
"userid": user.google_userid,
|
||||
})
|
||||
save = True
|
||||
|
||||
if save:
|
||||
user.save()
|
||||
|
||||
# Create Social Login Key(s) from Social Login Keys
|
||||
frappe.reload_doc("integrations", "doctype", "social_login_key", force=True)
|
||||
|
||||
social_login_keys = frappe.get_doc("Social Login Keys", "Social Login Keys")
|
||||
if social_login_keys.facebook_client_id or social_login_keys.facebook_client_secret:
|
||||
facebook_login_key = frappe.new_doc("Social Login Key")
|
||||
facebook_login_key.get_social_login_provider("Facebook", initialize=True)
|
||||
facebook_login_key.social_login_provider = "Facebook"
|
||||
facebook_login_key.client_id = social_login_keys.facebook_client_id
|
||||
facebook_login_key.client_secret = social_login_keys.facebook_client_secret
|
||||
if not (facebook_login_key.client_secret and facebook_login_key.client_id):
|
||||
facebook_login_key.enable_social_login = 0
|
||||
facebook_login_key.save()
|
||||
|
||||
if social_login_keys.frappe_server_url:
|
||||
frappe_login_key = frappe.new_doc("Social Login Key")
|
||||
frappe_login_key.get_social_login_provider("Frappe", initialize=True)
|
||||
frappe_login_key.social_login_provider = "Frappe"
|
||||
frappe_login_key.base_url = social_login_keys.frappe_server_url
|
||||
frappe_login_key.client_id = social_login_keys.frappe_client_id
|
||||
frappe_login_key.client_secret = social_login_keys.frappe_client_secret
|
||||
if not (frappe_login_key.client_secret and frappe_login_key.client_id and frappe_login_key.base_url):
|
||||
frappe_login_key.enable_social_login = 0
|
||||
frappe_login_key.save()
|
||||
|
||||
if social_login_keys.github_client_id or social_login_keys.github_client_secret:
|
||||
github_login_key = frappe.new_doc("Social Login Key")
|
||||
github_login_key.get_social_login_provider("GitHub", initialize=True)
|
||||
github_login_key.social_login_provider = "GitHub"
|
||||
github_login_key.client_id = social_login_keys.github_client_id
|
||||
github_login_key.client_secret = social_login_keys.github_client_secret
|
||||
if not (github_login_key.client_secret and github_login_key.client_id):
|
||||
github_login_key.enable_social_login = 0
|
||||
github_login_key.save()
|
||||
|
||||
if social_login_keys.google_client_id or social_login_keys.google_client_secret:
|
||||
google_login_key = frappe.new_doc("Social Login Key")
|
||||
google_login_key.get_social_login_provider("Google", initialize=True)
|
||||
google_login_key.social_login_provider = "Google"
|
||||
google_login_key.client_id = social_login_keys.google_client_id
|
||||
google_login_key.client_secret = social_login_keys.google_client_secret
|
||||
if not (google_login_key.client_secret and google_login_key.client_id):
|
||||
google_login_key.enable_social_login = 0
|
||||
google_login_key.save()
|
||||
|
||||
frappe.delete_doc("DocType", "Social Login Keys")
|
||||
|
|
@ -16,8 +16,13 @@ class TestFrappeOAuth2Client(unittest.TestCase):
|
|||
self.client_id = frappe.get_all("OAuth Client", fields=["*"])[0].get("client_id")
|
||||
|
||||
# Set Frappe server URL reqired for id_token generation
|
||||
frappe.db.set_value("Social Login Keys", None, "frappe_server_url", "http://localhost:8000")
|
||||
frappe.db.commit()
|
||||
try:
|
||||
frappe_login_key = frappe.get_doc("Social Login Key", "frappe")
|
||||
except frappe.DoesNotExistError:
|
||||
frappe_login_key = frappe.new_doc("Social Login Key")
|
||||
frappe_login_key.get_social_login_provider("Frappe", initialize=True)
|
||||
frappe_login_key.base_url = "http://localhost:8000"
|
||||
frappe_login_key.save()
|
||||
|
||||
def test_insert_note(self):
|
||||
|
||||
|
|
|
|||
|
|
@ -15,8 +15,13 @@ class TestOAuth20(unittest.TestCase):
|
|||
self.client_id = frappe.get_all("OAuth Client", fields=["*"])[0].get("client_id")
|
||||
|
||||
# Set Frappe server URL reqired for id_token generation
|
||||
frappe.db.set_value("Social Login Keys", None, "frappe_server_url", "http://localhost:8000")
|
||||
frappe.db.commit()
|
||||
try:
|
||||
frappe_login_key = frappe.get_doc("Social Login Key", "frappe")
|
||||
except frappe.DoesNotExistError:
|
||||
frappe_login_key = frappe.new_doc("Social Login Key")
|
||||
frappe_login_key.get_social_login_provider("Frappe", initialize=True)
|
||||
frappe_login_key.base_url = "http://localhost:8000"
|
||||
frappe_login_key.save()
|
||||
|
||||
def test_login_using_authorization_code(self):
|
||||
|
||||
|
|
@ -113,3 +118,6 @@ class TestOAuth20(unittest.TestCase):
|
|||
self.assertTrue(response_url.get("expires_in"))
|
||||
self.assertTrue(response_url.get("scope"))
|
||||
self.assertTrue(response_url.get("token_type"))
|
||||
|
||||
def tearDown(self):
|
||||
self.driver.close()
|
||||
|
|
|
|||
33
frappe/tests/ui/test_social_login_key_buttons.py
Normal file
33
frappe/tests/ui/test_social_login_key_buttons.py
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# MIT License. See license.txt
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import unittest, frappe, time
|
||||
from frappe.utils.selenium_testdriver import TestDriver
|
||||
|
||||
class TestSocialLoginKeyButtons(unittest.TestCase):
|
||||
def setUp(self):
|
||||
try:
|
||||
frappe_login_key = frappe.get_doc("Social Login Key", "frappe")
|
||||
except frappe.DoesNotExistError:
|
||||
frappe_login_key = frappe.new_doc("Social Login Key")
|
||||
frappe_login_key.get_social_login_provider("Frappe", initialize=True)
|
||||
frappe_login_key.base_url = "http://localhost:8000"
|
||||
frappe_login_key.enable_social_login = 1
|
||||
frappe_login_key.client_id = "test_client_id"
|
||||
frappe_login_key.client_secret = "test_client_secret"
|
||||
frappe_login_key.save()
|
||||
|
||||
self.driver = TestDriver()
|
||||
|
||||
def test_login_buttons(self):
|
||||
|
||||
# Go to Login Page
|
||||
self.driver.get("login")
|
||||
|
||||
time.sleep(2)
|
||||
frappe_social_login = self.driver.find(".btn-frappe")
|
||||
self.assertTrue(len(frappe_social_login) > 0)
|
||||
|
||||
def tearDown(self):
|
||||
self.driver.close()
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import json
|
||||
import json, re
|
||||
import bleach, bleach_whitelist.bleach_whitelist as bleach_whitelist
|
||||
from six import string_types
|
||||
|
||||
|
|
@ -48,6 +48,24 @@ def is_json(text):
|
|||
else:
|
||||
return True
|
||||
|
||||
def get_icon_html(icon, small=False):
|
||||
emoji_pattern = re.compile(u'['
|
||||
u'\U0001F300-\U0001F64F'
|
||||
u'\U0001F680-\U0001F6FF'
|
||||
u'\u2600-\u26FF\u2700-\u27BF]+',
|
||||
re.UNICODE)
|
||||
|
||||
if icon and emoji_pattern.match(icon):
|
||||
return '<span class="text-muted">' + icon + '</span>'
|
||||
|
||||
if frappe.utils.is_image(icon):
|
||||
return \
|
||||
'<img style="width: 16px; height: 16px;" src="{icon}">'.format(icon=icon) \
|
||||
if small else \
|
||||
'<img src="{icon}">'.format(icon=icon)
|
||||
else:
|
||||
return "<i class='{icon}'></i>".format(icon=icon)
|
||||
|
||||
# adapted from https://raw.githubusercontent.com/html5lib/html5lib-python/4aa79f113e7486c7ec5d15a6e1777bfe546d3259/html5lib/sanitizer.py
|
||||
acceptable_elements = [
|
||||
'a', 'abbr', 'acronym', 'address', 'area',
|
||||
|
|
@ -149,4 +167,4 @@ svg_attributes = [
|
|||
'xlink:href', 'xlink:role', 'xlink:show', 'xlink:title', 'xlink:type',
|
||||
'xml:base', 'xml:lang', 'xml:space', 'xmlns', 'xmlns:xlink', 'y',
|
||||
'y1', 'y2', 'zoomAndPan'
|
||||
]
|
||||
]
|
||||
|
|
|
|||
|
|
@ -4,91 +4,36 @@
|
|||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
import frappe.utils
|
||||
import json
|
||||
import json, jwt
|
||||
from frappe import _
|
||||
from frappe.utils.password import get_decrypted_password
|
||||
from six import string_types
|
||||
|
||||
class SignupDisabledError(frappe.PermissionError): pass
|
||||
|
||||
def get_oauth2_providers():
|
||||
out = {
|
||||
"google": {
|
||||
out = {}
|
||||
providers = frappe.get_all("Social Login Key", fields=["*"])
|
||||
for provider in providers:
|
||||
authorize_url, access_token_url = provider.authorize_url, provider.access_token_url
|
||||
if provider.custom_base_url:
|
||||
authorize_url = provider.base_url + provider.authorize_url
|
||||
access_token_url = provider.base_url + provider.access_token_url
|
||||
out[provider.name] = {
|
||||
"flow_params": {
|
||||
"name": "google",
|
||||
"authorize_url": "https://accounts.google.com/o/oauth2/auth",
|
||||
"access_token_url": "https://accounts.google.com/o/oauth2/token",
|
||||
"base_url": "https://www.googleapis.com",
|
||||
},
|
||||
|
||||
"redirect_uri": "/api/method/frappe.www.login.login_via_google",
|
||||
|
||||
"auth_url_data": {
|
||||
"scope": "https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email",
|
||||
"response_type": "code"
|
||||
},
|
||||
|
||||
# relative to base_url
|
||||
"api_endpoint": "oauth2/v2/userinfo"
|
||||
},
|
||||
|
||||
"github": {
|
||||
"flow_params": {
|
||||
"name": "github",
|
||||
"authorize_url": "https://github.com/login/oauth/authorize",
|
||||
"access_token_url": "https://github.com/login/oauth/access_token",
|
||||
"base_url": "https://api.github.com/"
|
||||
},
|
||||
|
||||
"redirect_uri": "/api/method/frappe.www.login.login_via_github",
|
||||
|
||||
# relative to base_url
|
||||
"api_endpoint": "user"
|
||||
},
|
||||
|
||||
"facebook": {
|
||||
"flow_params": {
|
||||
"name": "facebook",
|
||||
"authorize_url": "https://www.facebook.com/dialog/oauth",
|
||||
"access_token_url": "https://graph.facebook.com/oauth/access_token",
|
||||
"base_url": "https://graph.facebook.com"
|
||||
},
|
||||
|
||||
"redirect_uri": "/api/method/frappe.www.login.login_via_facebook",
|
||||
|
||||
"auth_url_data": {
|
||||
"display": "page",
|
||||
"response_type": "code",
|
||||
"scope": "email,public_profile"
|
||||
},
|
||||
|
||||
# relative to base_url
|
||||
"api_endpoint": "/v2.5/me",
|
||||
"api_endpoint_args": {
|
||||
"fields": "first_name,last_name,email,gender,location,verified,picture"
|
||||
"name": provider.name,
|
||||
"authorize_url": authorize_url,
|
||||
"access_token_url": access_token_url,
|
||||
"base_url": provider.base_url
|
||||
},
|
||||
"redirect_uri": provider.redirect_url,
|
||||
"api_endpoint": provider.api_endpoint,
|
||||
}
|
||||
}
|
||||
if provider.auth_url_data:
|
||||
out[provider.name]["auth_url_data"] = json.loads(provider.auth_url_data)
|
||||
|
||||
frappe_server_url = frappe.db.get_value("Social Login Keys", None, "frappe_server_url")
|
||||
if frappe_server_url:
|
||||
out['frappe'] = {
|
||||
"flow_params": {
|
||||
"name": "frappe",
|
||||
"authorize_url": frappe_server_url + "/api/method/frappe.integrations.oauth2.authorize",
|
||||
"access_token_url": frappe_server_url + "/api/method/frappe.integrations.oauth2.get_token",
|
||||
"base_url": frappe_server_url
|
||||
},
|
||||
|
||||
"redirect_uri": "/api/method/frappe.www.login.login_via_frappe",
|
||||
|
||||
"auth_url_data": {
|
||||
"response_type": "code",
|
||||
"scope": "openid"
|
||||
},
|
||||
|
||||
# relative to base_url
|
||||
"api_endpoint": "/api/method/frappe.integrations.oauth2.openid_profile"
|
||||
}
|
||||
if provider.api_endpoint_args:
|
||||
out[provider.name]["api_endpoint_args"] = json.loads(provider.api_endpoint_args)
|
||||
|
||||
return out
|
||||
|
||||
|
|
@ -100,17 +45,13 @@ def get_oauth_keys(provider):
|
|||
|
||||
if not keys:
|
||||
# try database
|
||||
social = frappe.get_doc("Social Login Keys", "Social Login Keys")
|
||||
keys = {}
|
||||
for fieldname in ("client_id", "client_secret"):
|
||||
value = social.get("{provider}_{fieldname}".format(provider=provider, fieldname=fieldname))
|
||||
if not value:
|
||||
keys = {}
|
||||
break
|
||||
keys[fieldname] = value
|
||||
|
||||
client_id, client_secret = frappe.get_value("Social Login Key", provider, ["client_id", "client_secret"])
|
||||
client_secret = get_decrypted_password("Social Login Key", provider, "client_secret")
|
||||
keys = {
|
||||
"client_id": client_id,
|
||||
"client_secret": client_secret
|
||||
}
|
||||
return keys
|
||||
|
||||
else:
|
||||
return {
|
||||
"client_id": keys["client_id"],
|
||||
|
|
@ -169,7 +110,11 @@ def login_via_oauth2(provider, code, state, decoder=None):
|
|||
info = get_info_via_oauth(provider, code, decoder)
|
||||
login_oauth_user(info, provider=provider, state=state)
|
||||
|
||||
def get_info_via_oauth(provider, code, decoder=None):
|
||||
def login_via_oauth2_id_token(provider, code, state, decoder=None):
|
||||
info = get_info_via_oauth(provider, code, decoder, id_token=True)
|
||||
login_oauth_user(info, provider=provider, state=state)
|
||||
|
||||
def get_info_via_oauth(provider, code, decoder=None, id_token=False):
|
||||
flow = get_oauth2_flow(provider)
|
||||
oauth2_providers = get_oauth2_providers()
|
||||
|
||||
|
|
@ -186,9 +131,14 @@ def get_info_via_oauth(provider, code, decoder=None):
|
|||
|
||||
session = flow.get_auth_session(**args)
|
||||
|
||||
api_endpoint = oauth2_providers[provider].get("api_endpoint")
|
||||
api_endpoint_args = oauth2_providers[provider].get("api_endpoint_args")
|
||||
info = session.get(api_endpoint, params=api_endpoint_args).json()
|
||||
if id_token:
|
||||
parsed_access = json.loads(session.access_token_response.text)
|
||||
token = parsed_access['id_token']
|
||||
info = jwt.decode(token, flow.client_secret, verify=False)
|
||||
else:
|
||||
api_endpoint = oauth2_providers[provider].get("api_endpoint")
|
||||
api_endpoint_args = oauth2_providers[provider].get("api_endpoint_args")
|
||||
info = session.get(api_endpoint, params=api_endpoint_args).json()
|
||||
|
||||
if (("verified_email" in info and not info.get("verified_email"))
|
||||
or ("verified" in info and not info.get("verified"))):
|
||||
|
|
@ -289,26 +239,28 @@ def update_oauth_user(user, data, provider):
|
|||
frappe.respond_as_web_page(_('Not Allowed'), _('User {0} is disabled').format(user.email))
|
||||
return False
|
||||
|
||||
if provider=="facebook" and not user.get("fb_userid"):
|
||||
if provider=="facebook" and not user.get_social_login_userid(provider):
|
||||
save = True
|
||||
user.set_social_login_userid(provider, userid=data["id"], username=data.get("username"))
|
||||
user.update({
|
||||
"fb_username": data.get("username"),
|
||||
"fb_userid": data["id"],
|
||||
"user_image": "https://graph.facebook.com/{id}/picture".format(id=data["id"])
|
||||
})
|
||||
|
||||
elif provider=="google" and not user.get("google_userid"):
|
||||
elif provider=="google" and not user.get_social_login_userid(provider):
|
||||
save = True
|
||||
user.google_userid = data["id"]
|
||||
user.set_social_login_userid(provider, userid=data["id"])
|
||||
|
||||
elif provider=="github" and not user.get("github_userid"):
|
||||
elif provider=="github" and not user.get_social_login_userid(provider):
|
||||
save = True
|
||||
user.github_userid = data["id"]
|
||||
user.github_username = data["login"]
|
||||
user.set_social_login_userid(provider, userid=data["id"], username=data.get("login"))
|
||||
|
||||
elif provider=="frappe" and not user.get("frappe_userid"):
|
||||
elif provider=="frappe" and not user.get_social_login_userid(provider):
|
||||
save = True
|
||||
user.frappe_userid = data["sub"]
|
||||
user.set_social_login_userid(provider, userid=data["sub"])
|
||||
|
||||
elif provider=="office_365" and not user.get_social_login_userid(provider):
|
||||
save = True
|
||||
user.set_social_login_userid(provider, userid=data["sub"])
|
||||
|
||||
if save:
|
||||
user.flags.ignore_permissions = True
|
||||
|
|
|
|||
|
|
@ -3,7 +3,11 @@
|
|||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from zxcvbn import zxcvbn
|
||||
try:
|
||||
from zxcvbn import zxcvbn
|
||||
except Exception as e:
|
||||
import zxcvbn
|
||||
|
||||
import frappe
|
||||
from frappe import _
|
||||
|
||||
|
|
|
|||
|
|
@ -39,27 +39,11 @@
|
|||
<h6>{{ _("Or login with") }}</h6>
|
||||
|
||||
<p class="text-center" style="margin-top: 15px">
|
||||
{%- if facebook_login is defined %}
|
||||
<a href="{{ facebook_login }}"
|
||||
class="btn btn-default btn-xs btn-social btn-facebook">
|
||||
<i class="fa fa-facebook-official"></i> {{ _("Facebook") }}</a>
|
||||
{%- endif -%}
|
||||
|
||||
{%- if google_login is defined %}
|
||||
<a href="{{ google_login }}" class="btn btn-default btn-xs btn-social btn-google">
|
||||
<i class="fa fa-google-plus"></i> {{ _("Google") }}</a>
|
||||
{%- endif -%}
|
||||
|
||||
{%- if github_login is defined %}
|
||||
<a href="{{ github_login }}" class="btn btn-default btn-xs btn-social btn-github">
|
||||
<i class="fa fa-github"></i> {{ _("GitHub") }}</a>
|
||||
{%- endif -%}
|
||||
|
||||
{%- if frappe_login is defined %}
|
||||
<a href="{{ frappe_login }}" class="btn btn-default btn-xs btn-social">
|
||||
<img style='width: 16px; height: 16px;'
|
||||
src="/assets/frappe/images/favicon.png"> {{ _("Frappe") }}</a>
|
||||
{%- endif -%}
|
||||
{% for provider in provider_logins %}
|
||||
<a href="{{ provider.auth_url }}"
|
||||
class="btn btn-default btn-xs btn-social btn-{{ provider.name }}">
|
||||
{{ provider.icon }} {{ provider.provider_name }}</a>
|
||||
{% endfor %}
|
||||
</p>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -4,11 +4,13 @@
|
|||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
import frappe.utils
|
||||
from frappe.utils.oauth import get_oauth2_authorize_url, get_oauth_keys, login_via_oauth2, login_oauth_user as _login_oauth_user, redirect_post_login
|
||||
from frappe.utils.oauth import get_oauth2_authorize_url, get_oauth_keys, login_via_oauth2, login_via_oauth2_id_token, login_oauth_user as _login_oauth_user, redirect_post_login
|
||||
import json
|
||||
from frappe import _
|
||||
from frappe.auth import LoginManager
|
||||
from frappe.integrations.doctype.ldap_settings.ldap_settings import get_ldap_settings
|
||||
from frappe.utils.password import get_decrypted_password
|
||||
from frappe.utils.html_utils import get_icon_html
|
||||
|
||||
no_cache = True
|
||||
|
||||
|
|
@ -21,11 +23,20 @@ def get_context(context):
|
|||
context.no_header = True
|
||||
context.for_test = 'login.html'
|
||||
context["title"] = "Login"
|
||||
context["provider_logins"] = []
|
||||
context["disable_signup"] = frappe.utils.cint(frappe.db.get_value("Website Settings", "Website Settings", "disable_signup"))
|
||||
|
||||
for provider in ("google", "github", "facebook", "frappe"):
|
||||
if get_oauth_keys(provider):
|
||||
context["{provider}_login".format(provider=provider)] = get_oauth2_authorize_url(provider)
|
||||
providers = [i.name for i in frappe.get_all("Social Login Key", filters={"enable_social_login":1})]
|
||||
for provider in providers:
|
||||
client_id, base_url = frappe.get_value("Social Login Key", provider, ["client_id", "base_url"])
|
||||
client_secret = get_decrypted_password("Social Login Key", provider, "client_secret")
|
||||
icon = get_icon_html(frappe.get_value("Social Login Key", provider, "icon"), small=True)
|
||||
if (get_oauth_keys(provider) and client_secret and client_id and base_url):
|
||||
context.provider_logins.append({
|
||||
"name": provider,
|
||||
"provider_name": frappe.get_value("Social Login Key", provider, "provider_name"),
|
||||
"auth_url": get_oauth2_authorize_url(provider),
|
||||
"icon": icon
|
||||
})
|
||||
context["social_login"] = True
|
||||
|
||||
ldap_settings = get_ldap_settings()
|
||||
|
|
@ -59,6 +70,10 @@ def login_via_facebook(code, state):
|
|||
def login_via_frappe(code, state):
|
||||
login_via_oauth2("frappe", code, state, decoder=json.loads)
|
||||
|
||||
@frappe.whitelist(allow_guest=True)
|
||||
def login_via_office365(code, state):
|
||||
login_via_oauth2_id_token("office_365", code, state, decoder=json.loads)
|
||||
|
||||
@frappe.whitelist(allow_guest=True)
|
||||
def login_oauth_user(data=None, provider=None, state=None, email_id=None, key=None, generate_login_token=False):
|
||||
if not ((data and provider and state) or (email_id and key)):
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue