def activate(request, greeting_email_template_name='im/welcome_email.txt', helpdesk_email_template_name='im/helpdesk_notification.txt'): """ Activates the user identified by the ``auth`` request parameter, sends a welcome email and renews the user token. The view uses commit_manually decorator in order to ensure the user state will be updated only if the email will be send successfully. """ token = request.GET.get('auth') next = request.GET.get('next') if request.user.is_authenticated(): message = _(astakos_messages.LOGGED_IN_WARNING) messages.error(request, message) transaction.rollback() return HttpResponseRedirect(reverse('index')) try: user = AstakosUser.objects.get(verification_code=token) except AstakosUser.DoesNotExist: transaction.rollback() raise Http404 if user.email_verified: message = _(astakos_messages.ACCOUNT_ALREADY_VERIFIED) messages.error(request, message) return HttpResponseRedirect(reverse('index')) try: backend = activation_backends.get_backend() result = backend.handle_verification(user, token) backend.send_result_notifications(result, user) next = settings.ACTIVATION_REDIRECT_URL or next response = HttpResponseRedirect(reverse('index')) if user.is_active: response = prepare_response(request, user, next, renew=True) messages.success(request, _(result.message)) else: messages.warning(request, _(result.message)) except Exception: transaction.rollback() raise else: transaction.commit() return response
def activate(request, greeting_email_template_name='im/welcome_email.txt', helpdesk_email_template_name='im/helpdesk_notification.txt'): """ Activates the user identified by the ``auth`` request parameter, sends a welcome email and renews the user token. The user state will be updated only if the email will be send successfully. """ token = request.GET.get('auth', None) next = request.GET.get('next', None) if not token: raise PermissionDenied if request.user.is_authenticated(): message = _(astakos_messages.LOGGED_IN_WARNING) messages.error(request, message) return HttpResponseRedirect(reverse('index')) try: user = AstakosUser.objects.select_for_update().\ get(verification_code=token) except AstakosUser.DoesNotExist: messages.error(request, astakos_messages.INVALID_ACTIVATION_KEY) return HttpResponseRedirect(reverse('index')) if user.email_verified: message = _(astakos_messages.ACCOUNT_ALREADY_VERIFIED) messages.error(request, message) return HttpResponseRedirect(reverse('index')) backend = activation_backends.get_backend() result = backend.handle_verification(user, token) backend.send_result_notifications(result, user) next = settings.ACTIVATION_REDIRECT_URL or next or reverse('index') if user.is_active: response = prepare_response(request, user, next, renew=True) messages.success(request, _(result.message)) else: response = HttpResponseRedirect(reverse('index')) messages.warning(request, _(result.message)) return response
activation_backend.Result.PENDING_MODERATION: # user should be warned that his account is not active yet status = messages.WARNING else: status = messages.SUCCESS message = result.message activation_backend.send_result_notifications(result, user) # commit user entry transaction.commit() if user and user.is_active: # activation backend directly activated the user # log him in next = request.POST.get('next', '') response = prepare_response(request, user, next=next) return response messages.add_message(request, status, message) return HttpResponseRedirect(reverse(on_success)) ldap_login_form = None if 'ldap' in settings.IM_MODULES: ldap_login_form = LDAPLoginForm(request) return render_response(template_name, login_form=ldap_login_form, signup_form=form, third_party_token=third_party_token, provider=provider, context_instance=get_context(
def login(request, on_failure='im/login.html'): """ on_failure: the template name to render on login failure """ if request.method == 'GET': return HttpResponseRedirect(reverse('login')) was_limited = getattr(request, 'limited', False) form = LoginForm(data=request.POST, was_limited=was_limited, request=request) next = get_query(request).get('next', '') third_party_token = get_query(request).get('key', False) provider = auth.get_provider('local') if not form.is_valid(): if third_party_token: messages.info(request, provider.get_login_to_add_msg) return render_to_response(on_failure, { 'login_form': form, 'next': next, 'key': third_party_token }, context_instance=RequestContext(request)) # get the user from the cache user = form.user_cache provider = auth.get_provider('local', user) if not provider.get_login_policy: message = provider.get_login_disabled_msg messages.error(request, message) return HttpResponseRedirect(reverse('login')) message = None if not user: message = provider.get_authentication_failed_msg elif not user.is_active: message = user.get_inactive_message('local') elif not user.has_auth_provider('local'): # valid user logged in with no auth providers set, add local provider # and let him log in if not user.get_available_auth_providers(): user.add_auth_provider('local') else: message = _(astakos_messages.NO_LOCAL_AUTH) if message: messages.error(request, message) return render_to_response(on_failure, {'login_form': form}, context_instance=RequestContext(request)) response = prepare_response(request, user, next) if third_party_token: # use requests to assign the account he just authenticated with with # a third party provider account try: request.user.add_pending_auth_provider(third_party_token) except PendingThirdPartyUser.DoesNotExist: provider = auth.get_provider('local', request.user) messages.error(request, provider.get_add_failed_msg) provider = user.get_auth_provider('local') messages.success(request, provider.get_login_success_msg) response.set_cookie('astakos_last_login_method', 'local') return response
def handle_third_party_login(request, provider_module, identifier, provider_info=None, affiliation=None, third_party_key=None): if not provider_info: provider_info = {} if not affiliation: affiliation = provider_module.title() next_redirect = request.GET.get('next', request.session.get('next_url', None)) if 'next_url' in request.session: del request.session['next_url'] third_party_request_params = get_third_party_session_params(request) from_login = third_party_request_params.get('from_login', False) switch_from = third_party_request_params.get('switch_from', False) provider_data = {'affiliation': affiliation, 'info': provider_info} provider = auth.get_provider(provider_module, request.user, identifier, **provider_data) # an existing user accessed the view if request.user.is_authenticated(): if request.user.has_auth_provider(provider.module, identifier=identifier): return HttpResponseRedirect(reverse('edit_profile')) if provider.verified_exists(): provider.log("add failed (identifier exists to another user)") messages.error(request, provider.get_add_exists_msg) return HttpResponseRedirect(reverse('edit_profile')) # automatically add identifier provider to user if not switch_from and not provider.get_add_policy: # TODO: handle existing uuid message separately provider.log("user cannot add provider") messages.error(request, provider.get_add_failed_msg) return HttpResponseRedirect(reverse('edit_profile')) user = request.user if switch_from: existing_provider = \ request.user.auth_providers.active().get( pk=int(switch_from), module=provider_module).settings # this is not a provider removal so we don't not use # provider.remove_from_user. Use low level access to the provider # db instance. if not provider.verified_exists(): if provider.get_add_policy: existing_provider._instance.delete() existing_provider.log("removed") provider.add_to_user() provider.log("added") else: messages.error(request, provider.get_add_exists_msg) return HttpResponseRedirect(reverse('edit_profile')) messages.success(request, provider.get_switch_success_msg) return HttpResponseRedirect(reverse('edit_profile')) provider.add_to_user() provider.log("added") provider = user.get_auth_provider(provider_module, identifier) messages.success(request, provider.get_added_msg) return HttpResponseRedirect(reverse('edit_profile')) # astakos user exists ? try: user = AstakosUser.objects.get_auth_provider_user( provider_module, identifier=identifier, user__email_verified=True, ) except AstakosUser.DoesNotExist: # TODO: add a message ? redirec to login ? if astakos_messages.AUTH_PROVIDER_SIGNUP_FROM_LOGIN: messages.warning(request, astakos_messages.AUTH_PROVIDER_SIGNUP_FROM_LOGIN) raise if not third_party_key: third_party_key = get_pending_key(request) provider = user.get_auth_provider(provider_module, identifier) if user.is_active: if not provider.get_login_policy: messages.error(request, provider.get_login_disabled_msg) return HttpResponseRedirect(reverse('login')) # authenticate user response = prepare_response(request, user, next_redirect, 'renew' in request.GET) messages.success(request, provider.get_login_success_msg) add_pending_auth_provider(request, third_party_key, provider) response.set_cookie('astakos_last_login_method', provider_module) return response else: message = user.get_inactive_message(provider_module, identifier) messages.error(request, message) return HttpResponseRedirect(login_url(request))
def signup(request, template_name='im/signup.html', on_success='index', extra_context=None, activation_backend=None): """ Allows a user to create a local account. In case of GET request renders a form for entering the user information. In case of POST handles the signup. The user activation will be delegated to the backend specified by the ``activation_backend`` keyword argument if present, otherwise to the ``astakos.im.activation_backends.InvitationBackend`` if settings.ASTAKOS_INVITATIONS_ENABLED is True or ``astakos.im.activation_backends.SimpleBackend`` if not (see activation_backends); Upon successful user creation, if ``next`` url parameter is present the user is redirected there otherwise renders the same page with a success message. On unsuccessful creation, renders ``template_name`` with an error message. **Arguments** ``template_name`` A custom template to render. This is optional; if not specified, this will default to ``im/signup.html``. ``extra_context`` An dictionary of variables to add to the template context. ``on_success`` Resolvable view name to redirect on registration success. **Template:** im/signup.html or ``template_name`` keyword argument. """ extra_context = extra_context or {} if request.user.is_authenticated(): logger.info("%s already signed in, redirect to index", request.user.log_display) transaction.rollback() return HttpResponseRedirect(reverse('index')) provider = get_query(request).get('provider', 'local') if not auth.get_provider(provider).get_create_policy: logger.error("%s provider not available for signup", provider) transaction.rollback() raise PermissionDenied instance = None # user registered using third party provider third_party_token = request.REQUEST.get('third_party_token', None) unverified = None if third_party_token: # retreive third party entry. This was created right after the initial # third party provider handshake. pending = get_object_or_404(PendingThirdPartyUser, token=third_party_token) provider = pending.provider # clone third party instance into the corresponding AstakosUser instance = pending.get_user_instance() get_unverified = AstakosUserAuthProvider.objects.unverified # check existing unverified entries unverified = get_unverified(pending.provider, identifier=pending.third_party_identifier) if unverified and request.method == 'GET': messages.warning(request, unverified.get_pending_registration_msg) if unverified.user.moderated: messages.warning(request, unverified.get_pending_resend_activation_msg) else: messages.warning(request, unverified.get_pending_moderation_msg) # prepare activation backend based on current request if not activation_backend: activation_backend = activation_backends.get_backend() form_kwargs = {'instance': instance, 'request': request} if third_party_token: form_kwargs['third_party_token'] = third_party_token form = activation_backend.get_signup_form(provider, None, **form_kwargs) if request.method == 'POST': form = activation_backend.get_signup_form(provider, request.POST, **form_kwargs) if form.is_valid(): commited = False try: user = form.save(commit=False) # delete previously unverified accounts if AstakosUser.objects.user_exists(user.email): AstakosUser.objects.get_by_identifier(user.email).delete() # store_user so that user auth providers get initialized form.store_user(user, request) result = activation_backend.handle_registration(user) if result.status == \ activation_backend.Result.PENDING_MODERATION: # user should be warned that his account is not active yet status = messages.WARNING else: status = messages.SUCCESS message = result.message activation_backend.send_result_notifications(result, user) # commit user entry transaction.commit() # commited flag # in case an exception get raised from this point commited = True if user and user.is_active: # activation backend directly activated the user # log him in next = request.POST.get('next', '') response = prepare_response(request, user, next=next) return response messages.add_message(request, status, message) return HttpResponseRedirect(reverse(on_success)) except Exception, e: if not commited: transaction.rollback() raise
def login(request, template_name="im/login.html", on_failure='im/login.html', extra_context=None): """ on_failure: the template name to render on login failure """ if request.method == 'GET': extra_context = extra_context or {} third_party_token = request.GET.get('key', False) if third_party_token: messages.info(request, astakos_messages.AUTH_PROVIDER_LOGIN_TO_ADD) if request.user.is_authenticated(): return HttpResponseRedirect(reverse('landing')) extra_context["primary_provider"] = LOCAL_PROVIDER return render_response( template_name, login_form=LoginForm(request=request), context_instance=get_context(request, extra_context) ) was_limited = getattr(request, 'limited', False) form = LoginForm(data=request.POST, was_limited=was_limited, request=request) next = get_query(request).get('next', '') third_party_token = get_query(request).get('key', False) provider = auth.get_provider('local') if not form.is_valid(): if third_party_token: messages.info(request, provider.get_login_to_add_msg) return render_to_response( on_failure, {'login_form': form, 'next': next, 'key': third_party_token}, context_instance=get_context(request, primary_provider=LOCAL_PROVIDER)) # get the user from the cache user = form.user_cache provider = auth.get_provider('local', user) if not provider.get_login_policy: message = provider.get_login_disabled_msg messages.error(request, message) return HttpResponseRedirect(reverse('login')) message = None if not user: message = provider.get_authentication_failed_msg elif not user.is_active: message = user.get_inactive_message('local') elif not user.has_auth_provider('local'): # valid user logged in with no auth providers set, add local provider # and let him log in if not user.get_available_auth_providers(): user.add_auth_provider('local') else: message = _(astakos_messages.NO_LOCAL_AUTH) if message: messages.error(request, message) return render_to_response(on_failure, {'login_form': form}, context_instance=RequestContext(request)) response = prepare_response(request, user, next) if third_party_token: # use requests to assign the account he just authenticated with with # a third party provider account try: request.user.add_pending_auth_provider(third_party_token) except PendingThirdPartyUser.DoesNotExist: provider = auth.get_provider('local', request.user) messages.error(request, provider.get_add_failed_msg) provider = user.get_auth_provider('local') messages.success(request, provider.get_login_success_msg) response.set_cookie('astakos_last_login_method', 'local') provider.update_last_login_at() return response
user = form.create_user() result = activation_backend.handle_registration(user) if result.status == \ activation_backend.Result.PENDING_MODERATION: # user should be warned that his account is not active yet status = messages.WARNING else: status = messages.SUCCESS message = result.message activation_backend.send_result_notifications(result, user) if user and user.is_active: # activation backend directly activated the user # log him in next = request.POST.get('next', '') response = prepare_response(request, user, next=next) return response messages.add_message(request, status, message) return HttpResponseRedirect(reverse(on_success)) ldap_login_form = None if 'ldap' in settings.IM_MODULES: ldap_login_form = LDAPLoginForm(request) return render_response( template_name, login_form=ldap_login_form, signup_form=form, third_party_token=third_party_token, provider=provider,
def handle_third_party_login(request, provider_module, identifier, provider_info=None, affiliation=None, third_party_key=None): if not provider_info: provider_info = {} if not affiliation: affiliation = provider_module.title() next_redirect = request.GET.get( 'next', request.session.get('next_url', None)) if 'next_url' in request.session: del request.session['next_url'] third_party_request_params = get_third_party_session_params(request) from_login = third_party_request_params.get('from_login', False) switch_from = third_party_request_params.get('switch_from', False) provider_data = { 'affiliation': affiliation, 'info': provider_info } provider = auth.get_provider(provider_module, request.user, identifier, **provider_data) # an existing user accessed the view if request.user.is_authenticated(): if request.user.has_auth_provider(provider.module, identifier=identifier): return HttpResponseRedirect(reverse('edit_profile')) if provider.verified_exists(): provider.log("add failed (identifier exists to another user)") messages.error(request, provider.get_add_exists_msg) return HttpResponseRedirect(reverse('edit_profile')) # automatically add identifier provider to user if not switch_from and not provider.get_add_policy: # TODO: handle existing uuid message separately provider.log("user cannot add provider") messages.error(request, provider.get_add_failed_msg) return HttpResponseRedirect(reverse('edit_profile')) user = request.user if switch_from: existing_provider = \ request.user.auth_providers.active().get( pk=int(switch_from), module=provider_module).settings # this is not a provider removal so we don't not use # provider.remove_from_user. Use low level access to the provider # db instance. if not provider.verified_exists(): if provider.get_add_policy: existing_provider._instance.delete() existing_provider.log("removed") provider.add_to_user() provider.log("added") else: messages.error(request, provider.get_add_exists_msg) return HttpResponseRedirect(reverse('edit_profile')) messages.success(request, provider.get_switch_success_msg) return HttpResponseRedirect(reverse('edit_profile')) provider.add_to_user() provider.log("added") provider = user.get_auth_provider(provider_module, identifier) messages.success(request, provider.get_added_msg) return HttpResponseRedirect(reverse('edit_profile')) # astakos user exists ? try: user = AstakosUser.objects.get_auth_provider_user( provider_module, identifier=identifier, user__email_verified=True, ) except AstakosUser.DoesNotExist: # TODO: add a message ? redirec to login ? if astakos_messages.AUTH_PROVIDER_SIGNUP_FROM_LOGIN: messages.warning(request, astakos_messages.AUTH_PROVIDER_SIGNUP_FROM_LOGIN) raise if not third_party_key: third_party_key = get_pending_key(request) provider = user.get_auth_provider(provider_module, identifier) if user.is_active: if not provider.get_login_policy: messages.error(request, provider.get_login_disabled_msg) return HttpResponseRedirect(reverse('login')) # authenticate user response = prepare_response(request, user, next_redirect, 'renew' in request.GET) messages.success(request, provider.get_login_success_msg) add_pending_auth_provider(request, third_party_key, provider) response.set_cookie('astakos_last_login_method', provider_module) return response else: message = user.get_inactive_message(provider_module, identifier) messages.error(request, message) return HttpResponseRedirect(login_url(request))
def signup(request, template_name='im/signup.html', on_success='index', extra_context=None, activation_backend=None): """ Allows a user to create a local account. In case of GET request renders a form for entering the user information. In case of POST handles the signup. The user activation will be delegated to the backend specified by the ``activation_backend`` keyword argument if present, otherwise to the ``astakos.im.activation_backends.InvitationBackend`` if settings.ASTAKOS_INVITATIONS_ENABLED is True or ``astakos.im.activation_backends.SimpleBackend`` if not (see activation_backends); Upon successful user creation, if ``next`` url parameter is present the user is redirected there otherwise renders the same page with a success message. On unsuccessful creation, renders ``template_name`` with an error message. **Arguments** ``template_name`` A custom template to render. This is optional; if not specified, this will default to ``im/signup.html``. ``extra_context`` An dictionary of variables to add to the template context. ``on_success`` Resolvable view name to redirect on registration success. **Template:** im/signup.html or ``template_name`` keyword argument. """ extra_context = extra_context or {} if request.user.is_authenticated(): logger.info("%s already signed in, redirect to index", request.user.log_display) return HttpResponseRedirect(reverse('index')) provider = get_query(request).get('provider', 'local') if not auth.get_provider(provider).get_create_policy: logger.error("%s provider not available for signup", provider) raise PermissionDenied instance = None # user registered using third party provider third_party_token = request.REQUEST.get('third_party_token', None) unverified = None if third_party_token: # retreive third party entry. This was created right after the initial # third party provider handshake. pending = get_object_or_404(PendingThirdPartyUser, token=third_party_token) provider = pending.provider # clone third party instance into the corresponding AstakosUser instance = pending.get_user_instance() get_unverified = AstakosUserAuthProvider.objects.unverified # check existing unverified entries unverified = get_unverified(pending.provider, identifier=pending.third_party_identifier) if unverified and request.method == 'GET': messages.warning(request, unverified.get_pending_registration_msg) if unverified.user.moderated: messages.warning(request, unverified.get_pending_resend_activation_msg) else: messages.warning(request, unverified.get_pending_moderation_msg) # prepare activation backend based on current request if not activation_backend: activation_backend = activation_backends.get_backend() form_kwargs = {'instance': instance, 'request': request} if third_party_token: form_kwargs['third_party_token'] = third_party_token form = activation_backend.get_signup_form( provider, None, **form_kwargs) if request.method == 'POST': form = activation_backend.get_signup_form( provider, request.POST, **form_kwargs) if form.is_valid(): user = form.save(commit=False) # delete previously unverified accounts if AstakosUser.objects.user_exists(user.email): AstakosUser.objects.get_by_identifier(user.email).delete() # store_user so that user auth providers get initialized form.store_user(user, request) result = activation_backend.handle_registration(user) if result.status == \ activation_backend.Result.PENDING_MODERATION: # user should be warned that his account is not active yet status = messages.WARNING else: status = messages.SUCCESS message = result.message activation_backend.send_result_notifications(result, user) # commit user entry transaction.commit() if user and user.is_active: # activation backend directly activated the user # log him in next = request.POST.get('next', '') response = prepare_response(request, user, next=next) return response messages.add_message(request, status, message) return HttpResponseRedirect(reverse(on_success)) return render_response(template_name, signup_form=form, third_party_token=third_party_token, provider=provider, context_instance=get_context(request, extra_context))