<s> """<STR_LIT>""" <EOL> import datetime <EOL> import uuid <EOL> from pyramid . httpexceptions import HTTPFound <EOL> from pyramid . security import NO_PERMISSION_REQUIRED <EOL> import requests <EOL> from . . api import ( <EOL> AuthenticationComplete , <EOL> AuthenticationDenied , <EOL> register_provider , <EOL> ) <EOL> from . . compat import parse_qsl <EOL> from . . exceptions import CSRFError <EOL> from . . exceptions import ThirdPartyFailure <EOL> from . . settings import ProviderSettings <EOL> from . . utils import flat_url <EOL> class FacebookAuthenticationComplete ( AuthenticationComplete ) : <EOL> """<STR_LIT>""" <EOL> def includeme ( config ) : <EOL> config . add_directive ( '<STR_LIT>' , add_facebook_login ) <EOL> config . add_directive ( '<STR_LIT>' , <EOL> add_facebook_login_from_settings ) <EOL> def add_facebook_login_from_settings ( config , prefix = '<STR_LIT>' ) : <EOL> settings = config . registry . settings <EOL> p = ProviderSettings ( settings , prefix ) <EOL> p . update ( '<STR_LIT>' , required = True ) <EOL> p . update ( '<STR_LIT>' , required = True ) <EOL> p . update ( '<STR_LIT>' ) <EOL> p . update ( '<STR_LIT>' ) <EOL> p . update ( '<STR_LIT>' ) <EOL> config . add_facebook_login ( ** p . kwargs ) <EOL> def add_facebook_login ( config , <EOL> consumer_key , <EOL> consumer_secret , <EOL> scope = None , <EOL> login_path = '<STR_LIT>' , <EOL> callback_path = '<STR_LIT>' , <EOL> name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> provider = FacebookProvider ( name , consumer_key , consumer_secret , scope ) <EOL> config . add_route ( provider . login_route , login_path ) <EOL> config . add_view ( provider , attr = '<STR_LIT>' , route_name = provider . login_route , <EOL> permission = NO_PERMISSION_REQUIRED ) <EOL> config . add_route ( provider . callback_route , callback_path , <EOL> use_global_views = True , <EOL> factory = provider . callback ) <EOL> register_provider ( config , name , provider ) <EOL> class FacebookProvider ( object ) : <EOL> def __init__ ( self , name , consumer_key , consumer_secret , scope ) : <EOL> self . name = name <EOL> self . type = '<STR_LIT>' <EOL> self . consumer_key = consumer_key <EOL> self . consumer_secret = consumer_secret <EOL> self . scope = scope <EOL> self . display = '<STR_LIT>' <EOL> self . login_route = '<STR_LIT>' % name <EOL> self . callback_route = '<STR_LIT>' % name <EOL> def login ( self , request ) : <EOL> """<STR_LIT>""" <EOL> scope = request . POST . get ( '<STR_LIT>' , self . scope ) <EOL> display = request . POST . get ( '<STR_LIT>' , self . display ) <EOL> request . session [ '<STR_LIT>' ] = state = uuid . uuid4 ( ) . hex <EOL> fb_url = flat_url ( <EOL> '<STR_LIT>' , <EOL> scope = scope , <EOL> display = display , <EOL> client_id = self . consumer_key , <EOL> redirect_uri = request . route_url ( self . callback_route ) , <EOL> state = state ) <EOL> return HTTPFound ( location = fb_url ) <EOL> def callback ( self , request ) : <EOL> """<STR_LIT>""" <EOL> sess_state = request . session . pop ( '<STR_LIT>' , None ) <EOL> req_state = request . GET . get ( '<STR_LIT:state>' ) <EOL> if not sess_state or sess_state != req_state : <EOL> raise CSRFError ( <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' . format ( <EOL> req_state = req_state , <EOL> sess_state = sess_state <EOL> ) <EOL> ) <EOL> code = request . GET . get ( '<STR_LIT:code>' ) <EOL> if not code : <EOL> reason = request . GET . get ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> return AuthenticationDenied ( reason = reason , <EOL> provider_name = self . name , <EOL> provider_type = self . type ) <EOL> access_url = flat_url ( <EOL> '<STR_LIT>' , <EOL> client_id = self . consumer_key , <EOL> client_secret = self . consumer_secret , <EOL> redirect_uri = request . route_url ( self . callback_route ) , <EOL> code = code ) <EOL> r = requests . get ( access_url ) <EOL> if r . status_code != <NUM_LIT:200> : <EOL> raise ThirdPartyFailure ( "<STR_LIT>" % ( <EOL> r . status_code , r . content ) ) <EOL> access_token = dict ( parse_qsl ( r . text ) ) [ '<STR_LIT>' ] <EOL> graph_url = flat_url ( '<STR_LIT>' , <EOL> access_token = access_token ) <EOL> r = requests . get ( graph_url ) <EOL> if r . status_code != <NUM_LIT:200> : <EOL> raise ThirdPartyFailure ( "<STR_LIT>" % ( <EOL> r . status_code , r . content ) ) <EOL> fb_profile = r . json ( ) <EOL> profile = extract_fb_data ( fb_profile ) <EOL> cred = { '<STR_LIT>' : access_token } <EOL> return FacebookAuthenticationComplete ( profile = profile , <EOL> credentials = cred , <EOL> provider_name = self . name , <EOL> provider_type = self . type ) <EOL> def extract_fb_data ( data ) : <EOL> """<STR_LIT>""" <EOL> nick = None <EOL> link = data . get ( '<STR_LIT>' ) <EOL> if link : <EOL> last = link . split ( '<STR_LIT:/>' ) [ - <NUM_LIT:1> ] <EOL> if last != data [ '<STR_LIT:id>' ] : <EOL> nick = last <EOL> profile = { <EOL> '<STR_LIT>' : [ { '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : data [ '<STR_LIT:id>' ] } ] , <EOL> '<STR_LIT>' : data [ '<STR_LIT:name>' ] , <EOL> '<STR_LIT>' : nick or data [ '<STR_LIT:name>' ] , <EOL> } <EOL> gender = data . get ( '<STR_LIT>' ) <EOL> if gender : <EOL> profile [ '<STR_LIT>' ] = gender <EOL> email = data . get ( '<STR_LIT:email>' ) <EOL> if email : <EOL> profile [ '<STR_LIT>' ] = [ { '<STR_LIT:value>' : email , '<STR_LIT>' : True } ] <EOL> if data . get ( '<STR_LIT>' ) and email : <EOL> profile [ '<STR_LIT>' ] = email <EOL> tz = data . get ( '<STR_LIT>' ) <EOL> if tz : <EOL> offset = float ( tz ) <EOL> h = int ( offset ) <EOL> m = int ( abs ( offset - h ) * <NUM_LIT> ) <EOL> profile [ '<STR_LIT>' ] = '<STR_LIT>' . format ( h = h , m = m ) <EOL> bday = data . get ( '<STR_LIT>' ) <EOL> if bday : <EOL> try : <EOL> mth , day , yr = bday . split ( '<STR_LIT:/>' ) <EOL> date = datetime . date ( int ( yr ) , int ( mth ) , int ( day ) ) <EOL> profile [ '<STR_LIT>' ] = date . strftime ( '<STR_LIT>' ) <EOL> except ValueError : <EOL> pass <EOL> name = { } <EOL> pcard_map = { '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' } <EOL> for key , val in pcard_map . items ( ) : <EOL> part = data . get ( key ) <EOL> if part : <EOL> name [ val ] = part <EOL> name [ '<STR_LIT>' ] = data [ '<STR_LIT:name>' ] <EOL> profile [ '<STR_LIT:name>' ] = name <EOL> for k , v in profile . items ( ) : <EOL> if not v or ( isinstance ( v , list ) and not v [ <NUM_LIT:0> ] ) : <EOL> del profile [ k ] <EOL> return profile </s>
