def handle(self, *args, **options): """create an askbot user account, given email address, user name, (optionally) password and (also optionally) - the default email delivery schedule """ if options['email'] is None: raise CommandError('the --email argument is required') if options['username'] is None: raise CommandError('the --user-name argument is required') password = options['password'] email = options['email'] username = options['username'] frequency = options['frequency'] if frequency not in ('i', 'd', 'w', 'n'): raise CommandError('value of --frequency must be one of: ' 'i, d, w, n') user = models.User.objects.create_user(username, email) if password: user.set_password(password) user.save() subscription = {'subscribe': 'y'} email_feeds_form = forms.SimpleEmailSubscribeForm(subscription, frequency=frequency) if email_feeds_form.is_valid(): email_feeds_form.save(user) else: raise CommandError('\n'.join(email_feeds_form.errors))
def handle(self, *args, **options): """create an askbot user account, given email address, user name, (optionally) password and (also optionally) - the default email delivery schedule """ translation.activate(django_settings.LANGUAGE_CODE) if options['email'] is None: raise CommandError('the --email argument is required') if options['username'] is None: raise CommandError('the --user-name argument is required') password = options['password'] email = options['email'] username = options['username'] frequency = options['frequency'] user = models.User.objects.create_user(username, email) if password: user.set_password(password) user.save() subscription = {'subscribe': 'y'} email_feeds_form = forms.SimpleEmailSubscribeForm(subscription) if email_feeds_form.is_valid(): email_feeds_form.save(user) else: raise CommandError('\n'.join(email_feeds_form.errors))
def handle_noargs(self, **options): users = User.objects.annotate( subscription_count=Count('notification_subscriptions')).filter( subscription_count=0) for user in users: form = forms.SimpleEmailSubscribeForm({'subscribe': 'y'}) form.full_clean() form.save(user=user) transaction.commit()
def create_authenticated_user_account(username=None, email=None, password=None, user_identifier=None, login_provider_name=None, subscribe=False): """creates a user account, user association with the login method and the the default email subscriptions """ user = User.objects.create_user(username, email) user_registered.send(None, user=user) logging.debug('creating new openid user association for %s') if password: user.set_password(password) user.save() else: UserAssociation(openid_url=user_identifier, user=user, provider_name=login_provider_name, last_used_timestamp=datetime.datetime.now()).save() subscribe_form = askbot_forms.SimpleEmailSubscribeForm( {'subscribe': subscribe}) subscribe_form.full_clean() logging.debug('saving email feed settings') subscribe_form.save(user) logging.debug('logging the user in') user = authenticate(method='force', user_id=user.id) if user is None: error_message = 'please make sure that ' + \ 'askbot.deps.django_authopenid.backends.AuthBackend' + \ 'is in your settings.AUTHENTICATION_BACKENDS' raise Exception(error_message) return user
def handle(self, *args, **options): """create an askbot user account, given email address, user name, (optionally) password and (also optionally) - the default email delivery schedule """ translation.activate(django_settings.LANGUAGE_CODE) if options['email'] is None: raise CommandError('the --email argument is required') if options['username'] is None: raise CommandError('the --user-name argument is required') password = options['password'] email = options['email'] username = options['username'] status = options['status'] if status not in 'wamdsb': raise CommandError( 'Illegal value of --status %s. Allowed user statuses are: %s' \ % (status, STATUS_INFO) ) user = models.User.objects.create_user(username, email) user.set_status(options['status']) if password: user.set_password(password) subscription = {'subscribe': 'y'} email_feeds_form = forms.SimpleEmailSubscribeForm(subscription) if email_feeds_form.is_valid(): email_feeds_form.save(user) else: raise CommandError('\n'.join(email_feeds_form.errors)) user.save()
def signup_with_password(request): """Create a password-protected account template: authopenid/signup_with_password.html """ logging.debug(get_request_info(request)) next = get_next_url(request) login_form = forms.LoginForm(initial={'next': next}) #this is safe because second decorator cleans this field provider_name = request.REQUEST['login_provider'] if askbot_settings.USE_RECAPTCHA: RegisterForm = forms.SafeClassicRegisterForm else: RegisterForm = forms.ClassicRegisterForm logging.debug('request method was %s' % request.method) if request.method == 'POST': form = RegisterForm(request.POST) email_feeds_form = askbot_forms.SimpleEmailSubscribeForm(request.POST) #validation outside if to remember form values logging.debug('validating classic register form') form1_is_valid = form.is_valid() if form1_is_valid: logging.debug('classic register form validated') else: logging.debug('classic register form is not valid') form2_is_valid = email_feeds_form.is_valid() if form2_is_valid: logging.debug('email feeds form validated') else: logging.debug('email feeds form is not valid') if form1_is_valid and form2_is_valid: logging.debug('both forms are valid') next = form.cleaned_data['next'] username = form.cleaned_data['username'] password = form.cleaned_data['password1'] email = form.cleaned_data['email'] provider_name = form.cleaned_data['login_provider'] User.objects.create_user(username, email, password) logging.debug('new user %s created' % username) if provider_name != 'local': raise NotImplementedError('must run create external user code') user = authenticate(username=username, password=password, provider_name=provider_name, method='password') login(request, user) logging.debug('new user logged in') email_feeds_form.save(user) logging.debug('email feeds form saved') # send email #subject = _("Welcome email subject line") #message_template = get_emplate( # 'authopenid/confirm_email.txt' #) #message_context = Context({ # 'signup_url': askbot_settings.APP_URL + reverse('user_signin'), # 'username': username, # 'password': password, #}) #message = message_template.render(message_context) #send_mail(subject, message, settings.DEFAULT_FROM_EMAIL, # [user.email]) #logging.debug('new password acct created, confirmation email sent!') return HttpResponseRedirect(next) else: #todo: this can be solved with a decorator, maybe form.initial['login_provider'] = provider_name logging.debug('create classic account forms were invalid') else: #todo: here we have duplication of get_password_login_provider... form = RegisterForm(initial={ 'next': next, 'login_provider': provider_name }) email_feeds_form = askbot_forms.SimpleEmailSubscribeForm() logging.debug('printing legacy signup form') major_login_providers = util.get_major_login_providers() minor_login_providers = util.get_minor_login_providers() context_data = { 'form': form, 'page_class': 'openid-signin', 'email_feeds_form': email_feeds_form, 'major_login_providers': major_login_providers.values(), 'minor_login_providers': minor_login_providers.values(), 'login_form': login_form } return render_into_skin('authopenid/signup_with_password.html', context_data, request)
def register(request, login_provider_name=None, user_identifier=None): """ this function is used via it's own url with request.method=POST or as a simple function call from "finalize_generic_signin" in which case request.method must ge 'GET' and login_provider_name and user_identifier arguments must not be None this function may need to be refactored to simplify the usage pattern template : authopenid/complete.html """ logging.debug('') next_url = get_next_url(request) user = None is_redirect = False username = request.session.get('username', '') email = request.session.get('email', '') logging.debug('request method is %s' % request.method) register_form = forms.OpenidRegisterForm( initial={ 'next': next_url, 'username': request.session.get('username', ''), 'email': request.session.get('email', ''), }) email_feeds_form = askbot_forms.SimpleEmailSubscribeForm() if request.method == 'GET': assert (login_provider_name is not None) assert (user_identifier is not None) #store this data into the session #to persist for the post request request.session['login_provider_name'] = login_provider_name request.session['user_identifier'] = user_identifier elif request.method == 'POST': if 'login_provider_name' not in request.session \ or 'user_identifier' not in request.session: logging.critical('illegal attempt to register') return HttpResponseRedirect(reverse('user_signin')) #load this data from the session user_identifier = request.session['user_identifier'] login_provider_name = request.session['login_provider_name'] logging.debug('trying to create new account associated with openid') register_form = forms.OpenidRegisterForm(request.POST) email_feeds_form = askbot_forms.SimpleEmailSubscribeForm(request.POST) if not register_form.is_valid(): logging.debug('OpenidRegisterForm is INVALID') elif not email_feeds_form.is_valid(): logging.debug('SimpleEmailSubscribeForm is INVALID') else: logging.debug( 'OpenidRegisterForm and SimpleEmailSubscribeForm are valid') is_redirect = True username = register_form.cleaned_data['username'] email = register_form.cleaned_data['email'] user = User.objects.create_user(username, email) logging.debug('creating new openid user association for %s') UserAssociation( openid_url=user_identifier, user=user, provider_name=login_provider_name, last_used_timestamp=datetime.datetime.now()).save() del request.session['user_identifier'] del request.session['login_provider_name'] logging.debug('logging the user in') user = authenticate(method='force', user_id=user.id) if user is None: error_message = 'please make sure that ' + \ 'askbot.deps.django_authopenid.backends.AuthBackend' + \ 'is in your settings.AUTHENTICATION_BACKENDS' raise Exception(error_message) login(request, user) logging.debug('saving email feed settings') email_feeds_form.save(user) #check if we need to post a question that was added anonymously #this needs to be a function call becase this is also done #if user just logged in and did not need to create the new account if user != None: if askbot_settings.EMAIL_VALIDATION == True: logging.debug('sending email validation') send_new_email_key(user, nomessage=True) output = validation_email_sent(request) set_email_validation_message( user) #message set after generating view return output if user.is_authenticated(): logging.debug('success, send user to main page') return HttpResponseRedirect(reverse('index')) else: logging.debug('have really strange error') raise Exception( 'openid login failed') #should not ever get here providers = { 'yahoo': '<font color="purple">Yahoo!</font>', 'flickr': '<font color="#0063dc">flick</font><font color="#ff0084">r</font>™', 'google': 'Google™', 'aol': '<font color="#31658e">AOL</font>', 'myopenid': 'MyOpenID', } if login_provider_name not in providers: provider_logo = login_provider_name logging.error( 'openid provider named "%s" has no pretty customized logo' % login_provider_name) else: provider_logo = providers[login_provider_name] logging.debug('printing authopenid/complete.html output') data = { 'openid_register_form': register_form, 'email_feeds_form': email_feeds_form, 'provider': mark_safe(provider_logo), 'username': username, 'email': email, 'login_type': 'openid', 'gravatar_faq_url': reverse('faq') + '#gravatar', } return render_into_skin('authopenid/complete.html', data, request)
def signin( request, newquestion=False, #todo: not needed newanswer=False, #todo: not needed ): """ signin page. It manages the legacy authentification (user/password) and openid authentification url: /signin/ template : authopenid/signin.htm """ logging.debug('in signin view') on_failure = signin_failure email_feeds_form = askbot_forms.SimpleEmailSubscribeForm() next_url = get_next_url(request) logging.debug('next url is %s' % next_url) if next_url == reverse('user_signin'): next_url = '%(next)s?next=%(next)s' % {'next': next_url} login_form = forms.LoginForm(initial={'next': next_url}) #todo: get next url make it sticky if next is 'user_signin' if request.method == 'POST': login_form = forms.LoginForm(request.POST) if login_form.is_valid(): provider_name = login_form.cleaned_data['login_provider_name'] if login_form.cleaned_data['login_type'] == 'password': password_action = login_form.cleaned_data['password_action'] if askbot_settings.USE_LDAP_FOR_PASSWORD_LOGIN: assert (password_action == 'login') ldap_provider_name = askbot_settings.LDAP_PROVIDER_NAME username = login_form.cleaned_data['username'] if util.ldap_check_password( username, login_form.cleaned_data['password']): user = authenticate(ldap_user_id=username, provider_name=ldap_provider_name, method='ldap') if user is not None: login(request, user) return HttpResponseRedirect(next_url) else: return finalize_generic_signin( request=request, user=user, user_identifier=username, login_provider_name=ldap_provider_name, redirect_url=next_url) else: if password_action == 'login': user = authenticate( username=login_form.cleaned_data['username'], password=login_form.cleaned_data['password'], provider_name=provider_name, method='password') if user is None: login_form.set_password_login_error() else: login(request, user) #todo: here we might need to set cookies #for external login sites return HttpResponseRedirect(next_url) elif password_action == 'change_password': if request.user.is_authenticated(): new_password = \ login_form.cleaned_data['new_password'] AuthBackend.set_password( user=request.user, password=new_password, provider_name=provider_name) request.user.message_set.create( message=_('Your new password saved')) return HttpResponseRedirect(next_url) else: logging.critical('unknown password action %s' % password_action) raise Http404 elif login_form.cleaned_data['login_type'] == 'openid': #initiate communication process logging.debug('processing signin with openid submission') #todo: make a simple-use wrapper for openid protocol sreg_req = sreg.SRegRequest(optional=['nickname', 'email']) redirect_to = "%s%s?%s" % ( get_url_host(request), reverse('user_complete_signin'), urllib.urlencode({'next': next_url})) return ask_openid(request, login_form.cleaned_data['openid_url'], redirect_to, on_failure=signin_failure, sreg_request=sreg_req) elif login_form.cleaned_data['login_type'] == 'oauth': try: #this url may need to have "next" piggibacked onto callback_url = reverse('user_complete_oauth_signin') connection = util.OAuthConnection( provider_name, callback_url=callback_url) connection.start() request.session['oauth_token'] = connection.get_token() request.session['oauth_provider_name'] = provider_name request.session[ 'next_url'] = next_url #special case for oauth oauth_url = connection.get_auth_url(login_only=False) return HttpResponseRedirect(oauth_url) except util.OAuthError, e: logging.critical(unicode(e)) msg = _('Unfortunately, there was some problem when ' 'connecting to %(provider)s, please try again ' 'or use another provider') % { 'provider': provider_name } request.user.message_set.create(message=msg) elif login_form.cleaned_data['login_type'] == 'facebook': #have to redirect for consistency #there is a requirement that 'complete_signin' try: #this call may raise FacebookError user_id = util.get_facebook_user_id(request) user = authenticate(method='facebook', facebook_user_id=user_id) return finalize_generic_signin( request=request, user=user, user_identifier=user_id, login_provider_name=provider_name, redirect_url=next_url) except util.FacebookError, e: logging.critical(unicode(e)) msg = _('Unfortunately, there was some problem when ' 'connecting to %(provider)s, please try again ' 'or use another provider') % { 'provider': 'Facebook' } request.user.message_set.create(message=msg) else: #raise 500 error - unknown login type pass
def signin(request): """ signin page. It manages the legacy authentification (user/password) and openid authentification url: /signin/ template : authopenid/signin.htm """ logging.debug('in signin view') on_failure = signin_failure email_feeds_form = askbot_forms.SimpleEmailSubscribeForm() #we need a special priority on where to redirect on successful login #here: #1) url parameter "next" - if explicitly set #2) url from django setting LOGIN_REDIRECT_URL #3) home page of the forum login_redirect_url = getattr(settings, 'LOGIN_REDIRECT_URL', None) next_url = get_next_url(request, default=login_redirect_url) logging.debug('next url is %s' % next_url) if askbot_settings.ALLOW_ADD_REMOVE_LOGIN_METHODS == False \ and request.user.is_authenticated(): return HttpResponseRedirect(next_url) if next_url == reverse('user_signin'): next_url = '%(next)s?next=%(next)s' % {'next': next_url} login_form = forms.LoginForm(initial={'next': next_url}) #todo: get next url make it sticky if next is 'user_signin' if request.method == 'POST': login_form = forms.LoginForm(request.POST) if login_form.is_valid(): provider_name = login_form.cleaned_data['login_provider_name'] if login_form.cleaned_data['login_type'] == 'password': password_action = login_form.cleaned_data['password_action'] if askbot_settings.USE_LDAP_FOR_PASSWORD_LOGIN: assert (password_action == 'login') username = login_form.cleaned_data['username'] password = login_form.cleaned_data['password'] # will be None if authentication fails user = authenticate(username=username, password=password, method='ldap') if user is not None: login(request, user) return HttpResponseRedirect(next_url) else: return finalize_generic_signin( request=request, user=user, user_identifier=username, login_provider_name=provider_name, redirect_url=next_url) else: if password_action == 'login': user = authenticate( username=login_form.cleaned_data['username'], password=login_form.cleaned_data['password'], provider_name=provider_name, method='password') if user is None: login_form.set_password_login_error() else: login(request, user) #todo: here we might need to set cookies #for external login sites return HttpResponseRedirect(next_url) elif password_action == 'change_password': if request.user.is_authenticated(): new_password = \ login_form.cleaned_data['new_password'] AuthBackend.set_password( user=request.user, password=new_password, provider_name=provider_name) request.user.message_set.create( message=_('Your new password saved')) return HttpResponseRedirect(next_url) else: logging.critical('unknown password action %s' % password_action) raise Http404 elif login_form.cleaned_data['login_type'] == 'openid': #initiate communication process logging.debug('processing signin with openid submission') #todo: make a simple-use wrapper for openid protocol sreg_req = sreg.SRegRequest(optional=['nickname', 'email']) redirect_to = "%s%s?%s" % ( get_url_host(request), reverse('user_complete_signin'), urllib.urlencode({'next': next_url})) return ask_openid(request, login_form.cleaned_data['openid_url'], redirect_to, on_failure=signin_failure, sreg_request=sreg_req) elif login_form.cleaned_data['login_type'] == 'oauth': try: #this url may need to have "next" piggibacked onto callback_url = reverse('user_complete_oauth_signin') connection = util.OAuthConnection( provider_name, callback_url=callback_url) connection.start() request.session['oauth_token'] = connection.get_token() request.session['oauth_provider_name'] = provider_name request.session[ 'next_url'] = next_url #special case for oauth oauth_url = connection.get_auth_url(login_only=False) return HttpResponseRedirect(oauth_url) except util.OAuthError, e: logging.critical(unicode(e)) msg = _('Unfortunately, there was some problem when ' 'connecting to %(provider)s, please try again ' 'or use another provider') % { 'provider': provider_name } request.user.message_set.create(message=msg) elif login_form.cleaned_data['login_type'] == 'facebook': #have to redirect for consistency #there is a requirement that 'complete_signin' try: #this call may raise FacebookError user_id = util.get_facebook_user_id(request) user = authenticate(method='facebook', facebook_user_id=user_id) return finalize_generic_signin( request=request, user=user, user_identifier=user_id, login_provider_name=provider_name, redirect_url=next_url) except util.FacebookError, e: logging.critical(unicode(e)) msg = _('Unfortunately, there was some problem when ' 'connecting to %(provider)s, please try again ' 'or use another provider') % { 'provider': 'Facebook' } request.user.message_set.create(message=msg) elif login_form.cleaned_data['login_type'] == 'wordpress_site': #here wordpress_site means for a self hosted wordpress blog not a wordpress.com blog wp = Client(askbot_settings.WORDPRESS_SITE_URL, login_form.cleaned_data['username'], login_form.cleaned_data['password']) try: wp_user = wp.call(GetUserInfo()) custom_wp_openid_url = '%s?user_id=%s' % (wp.url, wp_user.user_id) user = authenticate(method='wordpress_site', wordpress_url=wp.url, wp_user_id=wp_user.user_id) return finalize_generic_signin( request=request, user=user, user_identifier=custom_wp_openid_url, login_provider_name=provider_name, redirect_url=next_url) except WpFault, e: logging.critical(unicode(e)) msg = _('The login password combination was not correct') request.user.message_set.create(message=msg)
def signup_with_password(request): """Create a password-protected account template: authopenid/signup_with_password.html """ logging.debug(get_request_info(request)) login_form = forms.LoginForm(initial={'next': get_next_url(request)}) #this is safe because second decorator cleans this field provider_name = request.REQUEST['login_provider'] if askbot_settings.USE_RECAPTCHA: RegisterForm = forms.SafeClassicRegisterForm else: RegisterForm = forms.ClassicRegisterForm logging.debug('request method was %s' % request.method) if request.method == 'POST': form = RegisterForm(request.POST) email_feeds_form = askbot_forms.SimpleEmailSubscribeForm(request.POST) #validation outside if to remember form values logging.debug('validating classic register form') form1_is_valid = form.is_valid() if form1_is_valid: logging.debug('classic register form validated') else: logging.debug('classic register form is not valid') form2_is_valid = email_feeds_form.is_valid() if form2_is_valid: logging.debug('email feeds form validated') else: logging.debug('email feeds form is not valid') if form1_is_valid and form2_is_valid: logging.debug('both forms are valid') next = form.cleaned_data['next'] username = form.cleaned_data['username'] password = form.cleaned_data['password1'] email = form.cleaned_data['email'] subscribe = email_feeds_form.cleaned_data['subscribe'] if askbot_settings.REQUIRE_VALID_EMAIL_FOR == 'nothing': user = create_authenticated_user_account(username=username, email=email, password=password, subscribe=subscribe) login(request, user) cleanup_post_register_session(request) return HttpResponseRedirect(get_next_url(request)) else: request.session['username'] = username request.session['email'] = email request.session['password'] = password request.session['subscribe'] = subscribe #todo: generate a key and save it in the session key = util.generate_random_key() email = request.session['email'] send_email_key(email, key, handler_url_name='verify_email_and_register') request.session['validation_code'] = key redirect_url = reverse('verify_email_and_register') + \ '?next=' + get_next_url(request) return HttpResponseRedirect(redirect_url) else: #todo: this can be solved with a decorator, maybe form.initial['login_provider'] = provider_name logging.debug('create classic account forms were invalid') else: #todo: here we have duplication of get_password_login_provider... form = RegisterForm(initial={ 'next': get_next_url(request), 'login_provider': provider_name }) email_feeds_form = askbot_forms.SimpleEmailSubscribeForm() logging.debug('printing legacy signup form') major_login_providers = util.get_enabled_major_login_providers() minor_login_providers = util.get_enabled_minor_login_providers() context_data = { 'form': form, 'page_class': 'openid-signin', 'email_feeds_form': email_feeds_form, 'major_login_providers': major_login_providers.values(), 'minor_login_providers': minor_login_providers.values(), 'login_form': login_form } return render_into_skin('authopenid/signup_with_password.html', context_data, request)
def register(request, login_provider_name=None, user_identifier=None): """ this function is used via it's own url with request.method=POST or as a simple function call from "finalize_generic_signin" in which case request.method must ge 'GET' and login_provider_name and user_identifier arguments must not be None this function may need to be refactored to simplify the usage pattern template : authopenid/complete.html """ logging.debug('') next_url = get_next_url(request) user = None username = request.session.get('username', '') email = request.session.get('email', '') logging.debug('request method is %s' % request.method) register_form = forms.OpenidRegisterForm( initial={ 'next': next_url, 'username': request.session.get('username', ''), 'email': request.session.get('email', ''), }) email_feeds_form = askbot_forms.SimpleEmailSubscribeForm() if request.method == 'GET': assert (login_provider_name is not None) assert (user_identifier is not None) #store this data into the session #to persist for the post request request.session['login_provider_name'] = login_provider_name request.session['user_identifier'] = user_identifier elif request.method == 'POST': if 'login_provider_name' not in request.session \ or 'user_identifier' not in request.session: logging.critical('illegal attempt to register') return HttpResponseRedirect(reverse('user_signin')) #load this data from the session user_identifier = request.session['user_identifier'] login_provider_name = request.session['login_provider_name'] logging.debug('trying to create new account associated with openid') register_form = forms.OpenidRegisterForm(request.POST) email_feeds_form = askbot_forms.SimpleEmailSubscribeForm(request.POST) if not register_form.is_valid(): logging.debug('OpenidRegisterForm is INVALID') elif not email_feeds_form.is_valid(): logging.debug('SimpleEmailSubscribeForm is INVALID') else: logging.debug( 'OpenidRegisterForm and SimpleEmailSubscribeForm are valid') username = register_form.cleaned_data['username'] email = register_form.cleaned_data['email'] subscribe = email_feeds_form.cleaned_data['subscribe'] if askbot_settings.REQUIRE_VALID_EMAIL_FOR == 'nothing': user = create_authenticated_user_account( username=username, email=email, user_identifier=user_identifier, login_provider_name=login_provider_name, subscribe=subscribe) login(request, user) cleanup_post_register_session(request) return HttpResponseRedirect(next_url) else: request.session['username'] = username request.session['email'] = email request.session['subscribe'] = subscribe key = util.generate_random_key() email = request.session['email'] send_email_key(email, key, handler_url_name='verify_email_and_register') request.session['validation_code'] = key redirect_url = reverse( 'verify_email_and_register') + '?next=' + next_url return HttpResponseRedirect(redirect_url) providers = { 'yahoo': '<font color="purple">Yahoo!</font>', 'flickr': '<font color="#0063dc">flick</font><font color="#ff0084">r</font>™', 'google': 'Google™', 'aol': '<font color="#31658e">AOL</font>', 'myopenid': 'MyOpenID', } if login_provider_name not in providers: provider_logo = login_provider_name logging.error( 'openid provider named "%s" has no pretty customized logo' % login_provider_name) else: provider_logo = providers[login_provider_name] logging.debug('printing authopenid/complete.html output') data = { 'openid_register_form': register_form, 'email_feeds_form': email_feeds_form, 'provider': mark_safe(provider_logo), 'username': username, 'email': email, 'login_type': 'openid', 'gravatar_faq_url': reverse('faq') + '#gravatar', } return render_into_skin('authopenid/complete.html', data, request)