<s> import json <EOL> import base64 <EOL> import urllib2 <EOL> import logging <EOL> import random <EOL> from itsdangerous import URLSafeSerializer <EOL> from rauth import OAuth2Service <EOL> from openid import oidutil , fetchers <EOL> from openid . consumer import consumer as openid <EOL> from openid . extensions import ax , sreg <EOL> from flask import Blueprint , render_template , request , redirect , url_for , abort , current_app , session <EOL> from acoustid . web import db <EOL> from acoustid . web . utils import require_user , is_our_url <EOL> from acoustid . models import Account , AccountOpenID , AccountGoogle <EOL> from acoustid . utils import generate_api_key <EOL> from acoustid . data . account import ( <EOL> lookup_account_id_by_mbuser , <EOL> lookup_account_id_by_openid , <EOL> insert_account , <EOL> get_account_details , <EOL> reset_account_apikey , <EOL> update_account_lastlogin , <EOL> is_moderator , <EOL> ) <EOL> logger = logging . getLogger ( __name__ ) <EOL> user_page = Blueprint ( '<STR_LIT:user>' , __name__ ) <EOL> openid_logger = logging . getLogger ( '<STR_LIT>' ) <EOL> def log_openid_messages ( message , level = <NUM_LIT:0> ) : <EOL> openid_logger . info ( message ) <EOL> oidutil . log = log_openid_messages <EOL> fetcher = fetchers . Urllib2Fetcher ( ) <EOL> fetcher . urlopen = lambda req : urllib2 . urlopen ( req , timeout = <NUM_LIT:5> ) <EOL> fetchers . setDefaultFetcher ( fetcher ) <EOL> @ user_page . route ( '<STR_LIT>' , methods = [ '<STR_LIT:GET>' , '<STR_LIT:POST>' ] ) <EOL> def login ( ) : <EOL> if '<STR_LIT:id>' in session : <EOL> return redirect ( url_for ( '<STR_LIT>' ) ) <EOL> errors = list ( request . args . getlist ( '<STR_LIT:error>' ) ) <EOL> if request . method == '<STR_LIT:POST>' : <EOL> login_method = request . form . get ( '<STR_LIT>' ) <EOL> if login_method == '<STR_LIT>' : <EOL> return musicbrainz_login ( ) <EOL> elif login_method == '<STR_LIT>' : <EOL> return google_login ( ) <EOL> elif login_method == '<STR_LIT>' : <EOL> return openid_login ( ) <EOL> return render_template ( '<STR_LIT>' , errors = errors , <EOL> return_url = request . values . get ( '<STR_LIT>' ) ) <EOL> def find_or_create_musicbrainz_user ( mb_user_name ) : <EOL> user = db . session . query ( Account ) . filter_by ( mbuser = mb_user_name ) . first ( ) <EOL> if user is not None : <EOL> return user <EOL> user = Account ( ) <EOL> user . name = mb_user_name <EOL> user . mbuser = mb_user_name <EOL> user . apikey = generate_api_key ( ) <EOL> user . submission_count = <NUM_LIT:0> <EOL> db . session . add ( user ) <EOL> db . session . flush ( ) <EOL> return user <EOL> def login_user_and_redirect ( user_id , return_url = None ) : <EOL> session [ '<STR_LIT:id>' ] = user_id <EOL> if not return_url : <EOL> return_url = request . values . get ( '<STR_LIT>' ) <EOL> if return_url and is_our_url ( return_url ) : <EOL> return redirect ( return_url ) <EOL> return redirect ( url_for ( '<STR_LIT>' ) ) <EOL> def handle_musicbrainz_oauth2_login ( ) : <EOL> musicbrainz = OAuth2Service ( <EOL> name = '<STR_LIT>' , <EOL> client_id = current_app . config [ '<STR_LIT>' ] , <EOL> client_secret = current_app . config [ '<STR_LIT>' ] , <EOL> base_url = '<STR_LIT>' , <EOL> authorize_url = '<STR_LIT>' , <EOL> access_token_url = '<STR_LIT>' , <EOL> ) <EOL> serializer = URLSafeSerializer ( current_app . config [ '<STR_LIT>' ] ) <EOL> code = request . args . get ( '<STR_LIT:code>' ) <EOL> if not code : <EOL> token = str ( random . getrandbits ( <NUM_LIT:64> ) ) <EOL> session [ '<STR_LIT>' ] = token <EOL> url = musicbrainz . get_authorize_url ( ** { <EOL> '<STR_LIT>' : '<STR_LIT:code>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : url_for ( '<STR_LIT>' , _external = True ) , <EOL> '<STR_LIT:state>' : serializer . dumps ( { <EOL> '<STR_LIT>' : request . values . get ( '<STR_LIT>' ) , <EOL> '<STR_LIT>' : token , <EOL> } ) , <EOL> } ) <EOL> return redirect ( url ) <EOL> serialized_state = request . args . get ( '<STR_LIT:state>' ) <EOL> if serialized_state : <EOL> state = serializer . loads ( serialized_state ) <EOL> else : <EOL> state = { } <EOL> token = session . get ( '<STR_LIT>' ) <EOL> if not token : <EOL> raise Exception ( '<STR_LIT>' ) <EOL> if token != state . get ( '<STR_LIT>' ) : <EOL> raise Exception ( '<STR_LIT>' ) <EOL> auth_session = musicbrainz . get_auth_session ( data = { <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT:code>' : code , <EOL> '<STR_LIT>' : url_for ( '<STR_LIT>' , _external = True ) , <EOL> } , decoder = json . loads ) <EOL> response = auth_session . get ( '<STR_LIT>' ) . json ( ) <EOL> user = find_or_create_musicbrainz_user ( response [ '<STR_LIT>' ] ) <EOL> logger . info ( '<STR_LIT>' , user . id , user . name ) <EOL> return login_user_and_redirect ( user . id , return_url = state . get ( '<STR_LIT>' ) ) <EOL> @ user_page . route ( '<STR_LIT>' ) <EOL> def musicbrainz_login ( ) : <EOL> try : <EOL> response = handle_musicbrainz_oauth2_login ( ) <EOL> db . session . commit ( ) <EOL> except Exception : <EOL> logger . exception ( '<STR_LIT>' ) <EOL> db . session . rollback ( ) <EOL> return redirect ( url_for ( '<STR_LIT>' , error = '<STR_LIT>' ) ) <EOL> return response <EOL> def handle_openid_login_request ( ) : <EOL> openid_url = request . form [ '<STR_LIT>' ] <EOL> try : <EOL> consumer = openid . Consumer ( session , None ) <EOL> openid_req = consumer . begin ( openid_url ) <EOL> except openid . DiscoveryFailure : <EOL> logger . exception ( '<STR_LIT>' ) <EOL> raise <EOL> else : <EOL> if openid_req is None : <EOL> raise Exception ( '<STR_LIT>' ) <EOL> else : <EOL> ax_req = ax . FetchRequest ( ) <EOL> ax_req . add ( ax . AttrInfo ( '<STR_LIT>' , <EOL> alias = '<STR_LIT:email>' ) ) <EOL> ax_req . add ( ax . AttrInfo ( '<STR_LIT>' , <EOL> alias = '<STR_LIT>' ) ) <EOL> openid_req . addExtension ( ax_req ) <EOL> url = openid_req . redirectURL ( get_openid_realm ( ) , <EOL> url_for ( '<STR_LIT>' , return_url = request . values . get ( '<STR_LIT>' ) , _external = True ) ) <EOL> return redirect ( url ) <EOL> raise Exception ( '<STR_LIT>' ) <EOL> def handle_openid_login_response ( ) : <EOL> conn = db . session . connection ( ) <EOL> consumer = openid . Consumer ( session , None ) <EOL> info = consumer . complete ( request . args , request . url ) <EOL> if info . status == openid . SUCCESS : <EOL> openid_url = info . identity_url <EOL> values = { } <EOL> ax_resp = ax . FetchResponse . fromSuccessResponse ( info ) <EOL> if ax_resp : <EOL> attrs = { <EOL> '<STR_LIT:email>' : '<STR_LIT>' , <EOL> '<STR_LIT:name>' : '<STR_LIT>' , <EOL> } <EOL> for name , uri in attrs . iteritems ( ) : <EOL> try : <EOL> value = ax_resp . getSingle ( uri ) <EOL> if value : <EOL> values [ name ] = value <EOL> except KeyError : <EOL> pass <EOL> account_id = lookup_account_id_by_openid ( conn , openid_url ) <EOL> if not account_id : <EOL> account_id , account_api_key = insert_account ( conn , { <EOL> '<STR_LIT:name>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : openid_url , <EOL> } ) <EOL> logger . info ( "<STR_LIT>" , <EOL> openid_url , account_id , values . get ( '<STR_LIT:email>' , '<STR_LIT>' ) , values . get ( '<STR_LIT:name>' , '<STR_LIT>' ) ) <EOL> return login_user_and_redirect ( account_id ) <EOL> elif info . status == openid . CANCEL : <EOL> raise Exception ( '<STR_LIT>' ) <EOL> else : <EOL> raise Exception ( '<STR_LIT>' ) <EOL> def handle_openid_login ( ) : <EOL> if '<STR_LIT>' in request . args : <EOL> return handle_openid_login_response ( ) <EOL> else : <EOL> return handle_openid_login_request ( ) <EOL> @ user_page . route ( '<STR_LIT>' ) <EOL> def openid_login ( ) : <EOL> try : <EOL> response = handle_openid_login ( ) <EOL> db . session . commit ( ) <EOL> except Exception : <EOL> logger . exception ( '<STR_LIT>' ) <EOL> db . session . rollback ( ) <EOL> return redirect ( url_for ( '<STR_LIT>' , error = '<STR_LIT>' ) ) <EOL> return response <EOL> def get_openid_realm ( ) : <EOL> return url_for ( '<STR_LIT>' , _external = True ) . rstrip ( '<STR_LIT:/>' ) <EOL> def find_or_create_google_user ( google_user_id , openid = None ) : <EOL> user = db . session . query ( Account ) . join ( AccountGoogle ) . filter ( AccountGoogle . google_user_id == google_user_id ) . first ( ) <EOL> if user is not None : <EOL> return user <EOL> if openid is not None : <EOL> user = db . session . query ( Account ) . join ( AccountOpenID ) . filter ( AccountOpenID . openid == openid ) . first ( ) <EOL> if user is not None : <EOL> db . session . query ( AccountOpenID ) . filter ( AccountOpenID . openid == openid ) . delete ( ) <EOL> logger . info ( "<STR_LIT>" , openid , google_user_id ) <EOL> if user is None : <EOL> user = Account ( ) <EOL> user . name = '<STR_LIT>' <EOL> user . apikey = generate_api_key ( ) <EOL> user . submission_count = <NUM_LIT:0> <EOL> db . session . add ( user ) <EOL> db . session . flush ( ) <EOL> logger . info ( "<STR_LIT>" , user . id , user . name ) <EOL> google_user = AccountGoogle ( ) <EOL> google_user . account = user <EOL> google_user . google_user_id = google_user_id <EOL> db . session . add ( google_user ) <EOL> logger . info ( "<STR_LIT>" , user . id , user . name , google_user_id ) <EOL> return user <EOL> def handle_google_oauth2_login ( ) : <EOL> google = OAuth2Service ( <EOL> name = '<STR_LIT>' , <EOL> client_id = current_app . config [ '<STR_LIT>' ] , <EOL> client_secret = current_app . config [ '<STR_LIT>' ] , <EOL> base_url = '<STR_LIT>' , <EOL> authorize_url = '<STR_LIT>' , <EOL> access_token_url = '<STR_LIT>' , <EOL> ) <EOL> code = request . args . get ( '<STR_LIT:code>' ) <EOL> if not code : <EOL> url = google . get_authorize_url ( ** { <EOL> '<STR_LIT>' : '<STR_LIT:code>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : url_for ( '<STR_LIT>' , _external = True ) , <EOL> '<STR_LIT>' : get_openid_realm ( ) , <EOL> } ) <EOL> return redirect ( url ) <EOL> response = json . loads ( google . get_raw_access_token ( data = { <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT:code>' : code , <EOL> '<STR_LIT>' : url_for ( '<STR_LIT>' , _external = True ) , <EOL> } ) . content ) <EOL> header , payload , secret = str ( response [ '<STR_LIT>' ] ) . split ( '<STR_LIT:.>' ) <EOL> payload += '<STR_LIT:=>' * ( <NUM_LIT:4> - ( len ( payload ) % <NUM_LIT:4> ) ) <EOL> id_token = json . loads ( base64 . urlsafe_b64decode ( payload ) ) <EOL> user = find_or_create_google_user ( <EOL> id_token [ '<STR_LIT>' ] , id_token . get ( '<STR_LIT>' ) ) <EOL> logger . info ( '<STR_LIT>' , user . id , user . name ) <EOL> return login_user_and_redirect ( user . id ) <EOL> @ user_page . route ( '<STR_LIT>' ) <EOL> def google_login ( ) : <EOL> try : <EOL> response = handle_google_oauth2_login ( ) <EOL> db . session . commit ( ) <EOL> except Exception : <EOL> logger . exception ( '<STR_LIT>' ) <EOL> db . session . rollback ( ) <EOL> return redirect ( url_for ( '<STR_LIT>' , error = '<STR_LIT>' ) ) <EOL> return response <EOL> @ user_page . route ( '<STR_LIT>' ) <EOL> def logout ( ) : <EOL> if '<STR_LIT:id>' in session : <EOL> del session [ '<STR_LIT:id>' ] <EOL> return redirect ( url_for ( '<STR_LIT>' ) ) <EOL> @ user_page . route ( '<STR_LIT>' ) <EOL> def api_key ( ) : <EOL> user = require_user ( ) <EOL> return render_template ( '<STR_LIT>' , title = '<STR_LIT>' , <EOL> apikey = user . apikey ) <EOL> @ user_page . route ( '<STR_LIT>' ) <EOL> def new_api_key ( ) : <EOL> user = require_user ( ) <EOL> user . apikey = generate_api_key ( ) <EOL> db . session . commit ( ) <EOL> return redirect ( url_for ( '<STR_LIT>' ) ) </s>
