Преглед на файлове

Build and Watch without passing site argument,

Finishing touches to Google OAuth
version-14
Anand Doshi преди 11 години
родител
ревизия
8333562e1a
променени са 10 файла, в които са добавени 110 реда и са изтрити 102 реда
  1. +4
    -4
      frappe/__init__.py
  2. +0
    -3
      frappe/build.py
  3. +7
    -1
      frappe/cli.py
  4. +0
    -47
      frappe/core/doctype/profile/profile.py
  5. +12
    -19
      frappe/core/doctype/profile/profile.txt
  6. +1
    -1
      frappe/handler.py
  7. +1
    -13
      frappe/templates/includes/login.js
  8. +1
    -2
      frappe/templates/pages/login.html
  9. +83
    -12
      frappe/templates/pages/login.py
  10. +1
    -0
      requirements.txt

+ 4
- 4
frappe/__init__.py Целия файл

@@ -119,14 +119,14 @@ def init(site, sites_path=None):


def get_site_config(): def get_site_config():
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") 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): if os.path.exists(site_config_filepath):
config.update(get_file_json(site_config_filepath)) config.update(get_file_json(site_config_filepath))
return _dict(config) return _dict(config)
def destroy(): def destroy():
"""closes connection and releases werkzeug local""" """closes connection and releases werkzeug local"""
if db: if db:


+ 0
- 3
frappe/build.py Целия файл

@@ -10,14 +10,12 @@ Build the `public` folders and setup languages


import os, sys, frappe, json, shutil import os, sys, frappe, json, shutil
from cssmin import cssmin from cssmin import cssmin
import frappe.translate


def bundle(no_compress): def bundle(no_compress):
"""concat / minify js files""" """concat / minify js files"""
# build js files # build js files
make_asset_dirs() make_asset_dirs()
build(no_compress) build(no_compress)
frappe.translate.clear_cache()
def watch(no_compress): def watch(no_compress):
"""watch and rebuild if necessary""" """watch and rebuild if necessary"""
@@ -32,7 +30,6 @@ def watch(no_compress):


def make_asset_dirs(): def make_asset_dirs():
assets_path = os.path.join(frappe.local.sites_path, "assets") 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 [ for dir_path in [
os.path.join(assets_path, 'js'), os.path.join(assets_path, 'js'),
os.path.join(assets_path, 'css')]: os.path.join(assets_path, 'css')]:


+ 7
- 1
frappe/cli.py Целия файл

@@ -8,7 +8,7 @@ import sys, os


import frappe import frappe


site_arg_optional = ['serve']
site_arg_optional = ['serve', 'build', 'watch']


def get_site(parsed_args): def get_site(parsed_args):
if not parsed_args.get("site") and os.path.exists(os.path.join(parsed_args["sites_path"], "currentsite.txt")): 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) exit(1)
elif site: elif site:
frappe.init(site, sites_path=sites_path) frappe.init(site, sites_path=sites_path)
else:
# site argument optional
frappe.init("", sites_path=sites_path)
run(fn, parsed_args) run(fn, parsed_args)
else: else:
run(fn, parsed_args) run(fn, parsed_args)
@@ -298,6 +301,7 @@ def latest(verbose=True, rebuild_website_config=True):
import frappe.model.sync import frappe.model.sync
from frappe.website import rebuild_config from frappe.website import rebuild_config
from frappe.utils.fixtures import sync_fixtures from frappe.utils.fixtures import sync_fixtures
import frappe.translate
frappe.connect() frappe.connect()
@@ -317,6 +321,8 @@ def latest(verbose=True, rebuild_website_config=True):
sync_fixtures() sync_fixtures()
frappe.translate.clear_cache()
except frappe.modules.patch_handler.PatchError, e: except frappe.modules.patch_handler.PatchError, e:
print "\n".join(frappe.local.patch_log_list) print "\n".join(frappe.local.patch_log_list)
raise raise


+ 0
- 47
frappe/core/doctype/profile/profile.py Целия файл

@@ -357,53 +357,6 @@ def reset_password(user):
return "Password reset details sent to your email." return "Password reset details sent to your email."
else: else:
return "No such user (%s)" % user 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): def profile_query(doctype, txt, searchfield, start, page_len, filters):
from frappe.widgets.reportview import get_match_cond from frappe.widgets.reportview import get_match_cond


+ 12
- 19
frappe/core/doctype/profile/profile.txt Целия файл

@@ -2,7 +2,7 @@
{ {
"creation": "2013-03-07 11:54:44", "creation": "2013-03-07 11:54:44",
"docstatus": 0, "docstatus": 0,
"modified": "2014-01-29 16:52:01",
"modified": "2014-02-26 17:40:31",
"modified_by": "Administrator", "modified_by": "Administrator",
"owner": "Administrator" "owner": "Administrator"
}, },
@@ -34,6 +34,7 @@
}, },
{ {
"cancel": 0, "cancel": 0,
"delete": 0,
"doctype": "DocPerm", "doctype": "DocPerm",
"name": "__common__", "name": "__common__",
"parent": "Profile", "parent": "Profile",
@@ -454,9 +455,9 @@
}, },
{ {
"doctype": "DocField", "doctype": "DocField",
"fieldname": "facebook_authentication",
"fieldname": "third_party_authentication",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"label": "Facebook Authentication",
"label": "Third Party Authentication",
"permlevel": 0 "permlevel": 0
}, },
{ {
@@ -475,9 +476,16 @@
"permlevel": 0, "permlevel": 0,
"read_only": 1 "read_only": 1
}, },
{
"doctype": "DocField",
"fieldname": "google_userid",
"fieldtype": "Data",
"label": "Google User ID",
"permlevel": 0,
"read_only": 1
},
{ {
"create": 1, "create": 1,
"delete": 1,
"doctype": "DocPerm", "doctype": "DocPerm",
"email": 1, "email": 1,
"permlevel": 0, "permlevel": 0,
@@ -489,7 +497,6 @@
}, },
{ {
"create": 0, "create": 0,
"delete": 0,
"doctype": "DocPerm", "doctype": "DocPerm",
"email": 1, "email": 1,
"permlevel": 0, "permlevel": 0,
@@ -497,23 +504,9 @@
"role": "All", "role": "All",
"write": 0 "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, "amend": 0,
"create": 0, "create": 0,
"delete": 0,
"doctype": "DocPerm", "doctype": "DocPerm",
"permlevel": 1, "permlevel": 1,
"report": 1, "report": 1,


+ 1
- 1
frappe/handler.py Целия файл

@@ -79,7 +79,7 @@ def handle():
else: else:
if frappe.local.request.method in ("POST", "PUT") and frappe.db: if frappe.local.request.method in ("POST", "PUT") and frappe.db:
frappe.db.commit() frappe.db.commit()
build_response() build_response()


if frappe.db: if frappe.db:


+ 1
- 13
frappe/templates/includes/login.js Целия файл

@@ -145,7 +145,7 @@ login.via_facebook = function() {
url:"/", url:"/",
type: "POST", type: "POST",
data: { data: {
cmd:"frappe.core.doctype.profile.profile.facebook_login",
cmd:"frappe.templates.pages.login.login_via_facebook",
data: JSON.stringify(response) data: JSON.stringify(response)
}, },
statusCode: login.login_handlers statusCode: login.login_handlers
@@ -174,15 +174,3 @@ frappe.ready(function() {
}); });


{%- endif %} {%- 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 -%}

+ 1
- 2
frappe/templates/pages/login.html Целия файл

@@ -23,8 +23,7 @@
{%- if google_sign_in is defined %} {%- if google_sign_in is defined %}
<p class="text-center"> <p class="text-center">
<p class="text-muted text-center" style="margin: 10px;">or</p> <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> {{ _("Login via Google") }}</a></p>
{%- endif -%} {%- endif -%}
<p class="text-center"> <p class="text-center">


+ 83
- 12
frappe/templates/pages/login.py Целия файл

@@ -4,6 +4,8 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import frappe, os import frappe, os
import httplib2 import httplib2
import json
from werkzeug.utils import redirect


no_cache = True no_cache = True


@@ -19,30 +21,99 @@ def get_context(context):
return context return context


def get_google_auth_url(): 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() 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 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'], 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) credentials = flow.step2_exchange(code)


http = httplib2.Http() http = httplib2.Http()
http = credentials.authorize(http) http = credentials.authorize(http)
resp, content = http.request('https://www.googleapis.com/oauth2/v2/userinfo', 'GET') 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
- 0
requirements.txt Целия файл

@@ -1,6 +1,7 @@
chardet chardet
cssmin cssmin
dropbox dropbox
rauth
oauth2client oauth2client
gunicorn gunicorn
httplib2 httplib2


Зареждане…
Отказ
Запис