Finishing touches to Google OAuthversion-14
@@ -119,14 +119,14 @@ def init(site, sites_path=None): | |||
def get_site_config(): | |||
config = {} | |||
sites_config_filepath = os.path.join(local.sites_path, "site_config.json") | |||
common_site_config_filepath = os.path.join(local.sites_path, "common_site_config.json") | |||
site_config_filepath = os.path.join(local.site_path, "site_config.json") | |||
if os.path.exists(sites_config_filepath): | |||
config = get_file_json(sites_config_filepath) | |||
if os.path.exists(common_site_config_filepath): | |||
config = get_file_json(common_site_config_filepath) | |||
if os.path.exists(site_config_filepath): | |||
config.update(get_file_json(site_config_filepath)) | |||
return _dict(config) | |||
def destroy(): | |||
"""closes connection and releases werkzeug local""" | |||
if db: | |||
@@ -10,14 +10,12 @@ Build the `public` folders and setup languages | |||
import os, sys, frappe, json, shutil | |||
from cssmin import cssmin | |||
import frappe.translate | |||
def bundle(no_compress): | |||
"""concat / minify js files""" | |||
# build js files | |||
make_asset_dirs() | |||
build(no_compress) | |||
frappe.translate.clear_cache() | |||
def watch(no_compress): | |||
"""watch and rebuild if necessary""" | |||
@@ -32,7 +30,6 @@ def watch(no_compress): | |||
def make_asset_dirs(): | |||
assets_path = os.path.join(frappe.local.sites_path, "assets") | |||
site_public_path = os.path.join(frappe.local.site_path, 'public') | |||
for dir_path in [ | |||
os.path.join(assets_path, 'js'), | |||
os.path.join(assets_path, 'css')]: | |||
@@ -8,7 +8,7 @@ import sys, os | |||
import frappe | |||
site_arg_optional = ['serve'] | |||
site_arg_optional = ['serve', 'build', 'watch'] | |||
def get_site(parsed_args): | |||
if not parsed_args.get("site") and os.path.exists(os.path.join(parsed_args["sites_path"], "currentsite.txt")): | |||
@@ -41,6 +41,9 @@ def main(): | |||
exit(1) | |||
elif site: | |||
frappe.init(site, sites_path=sites_path) | |||
else: | |||
# site argument optional | |||
frappe.init("", sites_path=sites_path) | |||
run(fn, parsed_args) | |||
else: | |||
run(fn, parsed_args) | |||
@@ -298,6 +301,7 @@ def latest(verbose=True, rebuild_website_config=True): | |||
import frappe.model.sync | |||
from frappe.website import rebuild_config | |||
from frappe.utils.fixtures import sync_fixtures | |||
import frappe.translate | |||
frappe.connect() | |||
@@ -317,6 +321,8 @@ def latest(verbose=True, rebuild_website_config=True): | |||
sync_fixtures() | |||
frappe.translate.clear_cache() | |||
except frappe.modules.patch_handler.PatchError, e: | |||
print "\n".join(frappe.local.patch_log_list) | |||
raise | |||
@@ -357,53 +357,6 @@ def reset_password(user): | |||
return "Password reset details sent to your email." | |||
else: | |||
return "No such user (%s)" % user | |||
@frappe.whitelist(allow_guest=True) | |||
def facebook_login(data): | |||
data = json.loads(data) | |||
if not (data.get("id") and data.get("fb_access_token")): | |||
raise frappe.ValidationError | |||
user = data["email"] | |||
if not get_fb_userid(data.get("fb_access_token")): | |||
# garbage | |||
raise frappe.ValidationError | |||
if not frappe.db.exists("Profile", user): | |||
if data.get("birthday"): | |||
b = data.get("birthday").split("/") | |||
data["birthday"] = b[2] + "-" + b[0] + "-" + b[1] | |||
profile = frappe.bean({ | |||
"doctype":"Profile", | |||
"first_name": data["first_name"], | |||
"last_name": data["last_name"], | |||
"email": data["email"], | |||
"enabled": 1, | |||
"new_password": frappe.generate_hash(data["email"]), | |||
"fb_username": data["username"], | |||
"fb_userid": data["id"], | |||
"location": data.get("location", {}).get("name"), | |||
"birth_date": data.get("birthday"), | |||
"user_type": "Website User" | |||
}) | |||
profile.ignore_permissions = True | |||
profile.get_controller().no_welcome_mail = True | |||
profile.insert() | |||
frappe.local.login_manager.user = user | |||
frappe.local.login_manager.post_login() | |||
def get_fb_userid(fb_access_token): | |||
import requests | |||
response = requests.get("https://graph.facebook.com/me?access_token=" + fb_access_token) | |||
if response.status_code==200: | |||
print response.json() | |||
return response.json().get("id") | |||
else: | |||
return frappe.AuthenticationError | |||
def profile_query(doctype, txt, searchfield, start, page_len, filters): | |||
from frappe.widgets.reportview import get_match_cond | |||
@@ -2,7 +2,7 @@ | |||
{ | |||
"creation": "2013-03-07 11:54:44", | |||
"docstatus": 0, | |||
"modified": "2014-01-29 16:52:01", | |||
"modified": "2014-02-26 17:40:31", | |||
"modified_by": "Administrator", | |||
"owner": "Administrator" | |||
}, | |||
@@ -34,6 +34,7 @@ | |||
}, | |||
{ | |||
"cancel": 0, | |||
"delete": 0, | |||
"doctype": "DocPerm", | |||
"name": "__common__", | |||
"parent": "Profile", | |||
@@ -454,9 +455,9 @@ | |||
}, | |||
{ | |||
"doctype": "DocField", | |||
"fieldname": "facebook_authentication", | |||
"fieldname": "third_party_authentication", | |||
"fieldtype": "Section Break", | |||
"label": "Facebook Authentication", | |||
"label": "Third Party Authentication", | |||
"permlevel": 0 | |||
}, | |||
{ | |||
@@ -475,9 +476,16 @@ | |||
"permlevel": 0, | |||
"read_only": 1 | |||
}, | |||
{ | |||
"doctype": "DocField", | |||
"fieldname": "google_userid", | |||
"fieldtype": "Data", | |||
"label": "Google User ID", | |||
"permlevel": 0, | |||
"read_only": 1 | |||
}, | |||
{ | |||
"create": 1, | |||
"delete": 1, | |||
"doctype": "DocPerm", | |||
"email": 1, | |||
"permlevel": 0, | |||
@@ -489,7 +497,6 @@ | |||
}, | |||
{ | |||
"create": 0, | |||
"delete": 0, | |||
"doctype": "DocPerm", | |||
"email": 1, | |||
"permlevel": 0, | |||
@@ -497,23 +504,9 @@ | |||
"role": "All", | |||
"write": 0 | |||
}, | |||
{ | |||
"create": 0, | |||
"delete": 0, | |||
"doctype": "DocPerm", | |||
"email": 1, | |||
"permlevel": 0, | |||
"print": 1, | |||
"report": 1, | |||
"restricted": 1, | |||
"role": "All", | |||
"submit": 0, | |||
"write": 0 | |||
}, | |||
{ | |||
"amend": 0, | |||
"create": 0, | |||
"delete": 0, | |||
"doctype": "DocPerm", | |||
"permlevel": 1, | |||
"report": 1, | |||
@@ -79,7 +79,7 @@ def handle(): | |||
else: | |||
if frappe.local.request.method in ("POST", "PUT") and frappe.db: | |||
frappe.db.commit() | |||
build_response() | |||
if frappe.db: | |||
@@ -145,7 +145,7 @@ login.via_facebook = function() { | |||
url:"/", | |||
type: "POST", | |||
data: { | |||
cmd:"frappe.core.doctype.profile.profile.facebook_login", | |||
cmd:"frappe.templates.pages.login.login_via_facebook", | |||
data: JSON.stringify(response) | |||
}, | |||
statusCode: login.login_handlers | |||
@@ -174,15 +174,3 @@ frappe.ready(function() { | |||
}); | |||
{%- endif %} | |||
{% if google_sign_in is defined -%} | |||
frappe.ready(function() { | |||
$(".btn-google").click(function() { | |||
frappe.call({ | |||
method: "frappe.templates.pages.login.get_google_auth_url" | |||
}) | |||
}) | |||
}) | |||
{%- endif -%} |
@@ -23,8 +23,7 @@ | |||
{%- if google_sign_in is defined %} | |||
<p class="text-center"> | |||
<p class="text-muted text-center" style="margin: 10px;">or</p> | |||
<a href="{{ google_sign_in }}" target="_blank" | |||
type="button" class="btn btn-lg btn-primary btn-block btn-google"> | |||
<a href="{{ google_sign_in }}" type="button" class="btn btn-lg btn-primary btn-block btn-google"> | |||
{{ _("Login via Google") }}</a></p> | |||
{%- endif -%} | |||
<p class="text-center"> | |||
@@ -4,6 +4,8 @@ | |||
from __future__ import unicode_literals | |||
import frappe, os | |||
import httplib2 | |||
import json | |||
from werkzeug.utils import redirect | |||
no_cache = True | |||
@@ -19,30 +21,99 @@ def get_context(context): | |||
return context | |||
def get_google_auth_url(): | |||
from oauth2client.client import flow_from_clientsecrets | |||
flow = flow_from_clientsecrets(frappe.get_site_path("google_config.json"), | |||
scope=['https://www.googleapis.com/auth/userinfo.profile', 'https://www.googleapis.com/auth/userinfo.email'], | |||
redirect_uri='http://localhost:8000/api/method/frappe.templates.pages.login.login_via_google') | |||
flow = get_google_auth_flow() | |||
return flow.step1_get_authorize_url() | |||
@frappe.whitelist(allow_guest=True) | |||
def login_via_google(code): | |||
def get_google_auth_flow(): | |||
from oauth2client.client import flow_from_clientsecrets | |||
google_config_path = frappe.get_site_path("google_config.json") | |||
google_config = frappe.get_file_json(google_config_path) | |||
flow = flow_from_clientsecrets(frappe.get_site_path("google_config.json"), | |||
flow = flow_from_clientsecrets(google_config_path, | |||
scope=['https://www.googleapis.com/auth/userinfo.profile', 'https://www.googleapis.com/auth/userinfo.email'], | |||
redirect_uri='http://localhost:8000/api/method/frappe.templates.pages.login.login_via_google') | |||
redirect_uri=google_config.get("web").get("redirect_uris")[0]) | |||
return flow | |||
@frappe.whitelist(allow_guest=True) | |||
def login_via_google(code): | |||
flow = get_google_auth_flow() | |||
credentials = flow.step2_exchange(code) | |||
http = httplib2.Http() | |||
http = credentials.authorize(http) | |||
resp, content = http.request('https://www.googleapis.com/oauth2/v2/userinfo', 'GET') | |||
info = json.loads(content) | |||
print content | |||
if not info.get("verified_email"): | |||
frappe.throw("You need to verify your email with Google before you can proceed.") | |||
frappe.local._response = redirect("/") | |||
login_oauth_user(info, oauth_provider="google") | |||
# because of a GET request! | |||
frappe.db.commit() | |||
@frappe.whitelist(allow_guest=True) | |||
def login_via_facebook(data): | |||
data = json.loads(data) | |||
if not (data.get("id") and data.get("fb_access_token")): | |||
raise frappe.ValidationError | |||
if not get_fb_userid(data.get("fb_access_token")): | |||
# garbage | |||
raise frappe.ValidationError | |||
login_oauth_user(data, oauth_provider="facebook") | |||
def login_oauth_user(data, oauth_provider=None): | |||
user = data["email"] | |||
if not frappe.db.exists("Profile", user): | |||
create_oauth_user(data, oauth_provider) | |||
frappe.local.login_manager.user = user | |||
frappe.local.login_manager.post_login() | |||
def create_oauth_user(data, oauth_provider): | |||
if data.get("birthday"): | |||
b = data.get("birthday").split("/") | |||
data["birthday"] = b[2] + "-" + b[0] + "-" + b[1] | |||
profile = frappe.bean({ | |||
"doctype":"Profile", | |||
"first_name": data.get("first_name") or data.get("given_name"), | |||
"last_name": data.get("last_name") or data.get("family_name"), | |||
"email": data["email"], | |||
"gender": data.get("gender"), | |||
"enabled": 1, | |||
"new_password": frappe.generate_hash(data["email"]), | |||
"location": data.get("location", {}).get("name"), | |||
"birth_date": data.get("birthday"), | |||
"user_type": "Website User", | |||
"user_image": data.get("picture") | |||
}) | |||
if oauth_provider=="facebook": | |||
profile.doc.fields.update({ | |||
"fb_username": data["username"], | |||
"fb_userid": data["id"] | |||
}) | |||
elif oauth_provider=="google": | |||
profile.doc.google_userid = data["id"] | |||
profile.ignore_permissions = True | |||
profile.get_controller().no_welcome_mail = True | |||
profile.insert() | |||
def get_fb_userid(fb_access_token): | |||
import requests | |||
response = requests.get("https://graph.facebook.com/me?access_token=" + fb_access_token) | |||
if response.status_code==200: | |||
print response.json() | |||
return response.json().get("id") | |||
else: | |||
return frappe.AuthenticationError |
@@ -1,6 +1,7 @@ | |||
chardet | |||
cssmin | |||
dropbox | |||
rauth | |||
oauth2client | |||
gunicorn | |||
httplib2 | |||