def create(self, validated_data, **kwargs): if "view" not in self.context or not self.context["view"].kwargs.get( "invite_id"): raise serializers.ValidationError( "Please provide an invite ID to continue.") user: Optional[User] = None is_new_user: bool = False if self.context["request"].user.is_authenticated: user = cast(User, self.context["request"].user) invite_id = self.context["view"].kwargs.get("invite_id") try: invite: OrganizationInvite = OrganizationInvite.objects.select_related( "organization").get(id=invite_id) except (OrganizationInvite.DoesNotExist): raise serializers.ValidationError( "The provided invite ID is not valid.") with transaction.atomic(): if not user: is_new_user = True user = User.objects.create_user( invite.target_email, validated_data.pop("password"), validated_data.pop("first_name"), **validated_data, ) try: invite.use(user) except ValueError as e: raise serializers.ValidationError(str(e)) if is_new_user: login( self.context["request"], user, backend="django.contrib.auth.backends.ModelBackend", ) report_user_signed_up( user.distinct_id, is_instance_first_user=False, is_organization_first_user=False, new_onboarding_enabled=( not invite.organization.setup_section_2_completed), backend_processor="OrganizationInviteSignupSerializer", ) else: report_user_joined_organization(organization=invite.organization, current_user=user) # Update user props user_identify.identify_task.delay(user_id=user.id) return user
def create(self, validated_data, **kwargs): if settings.DEMO: return self.enter_demo(validated_data) is_instance_first_user: bool = not User.objects.exists() organization_name = validated_data.pop("organization_name", validated_data["first_name"]) self._organization, self._team, self._user = User.objects.bootstrap( organization_name=organization_name, create_team=self.create_team, **validated_data, is_staff=is_instance_first_user, ) user = self._user login( self.context["request"], user, backend="django.contrib.auth.backends.ModelBackend", ) report_user_signed_up( user, is_instance_first_user=is_instance_first_user, is_organization_first_user=True, new_onboarding_enabled=(not self._organization.setup_section_2_completed), backend_processor="OrganizationSignupSerializer", user_analytics_metadata=user.get_analytics_metadata(), org_analytics_metadata=user.organization.get_analytics_metadata() if user.organization else None, ) return user
def create(self, validated_data, **kwargs): is_instance_first_user: bool = not User.objects.exists() organization_name = validated_data.pop("organization_name", validated_data["first_name"]) self._organization, self._team, self._user = User.objects.bootstrap( organization_name=organization_name, create_team=self.create_team, **validated_data, ) user = self._user # Temp (due to FF-release [`new-onboarding-2822`]): Activate the setup/onboarding process if applicable if self.enable_new_onboarding(user): self._organization.setup_section_2_completed = False self._organization.save() login( self.context["request"], user, backend="django.contrib.auth.backends.ModelBackend", ) report_user_signed_up( user.distinct_id, is_instance_first_user=is_instance_first_user, is_organization_first_user=True, new_onboarding_enabled=( not self._organization.setup_section_2_completed), backend_processor="OrganizationSignupSerializer", ) return user
def signup_to_organization_view(request, invite_id): """ TODO: DEPRECATED in favor of posthog.api.organization.OrganizationInviteSignupSerializer """ if not invite_id: return redirect("/") if not User.objects.exists(): return redirect("/preflight") try: invite: Union[ OrganizationInvite, TeamInviteSurrogate] = OrganizationInvite.objects.select_related( "organization").get(id=invite_id) except (OrganizationInvite.DoesNotExist, ValidationError): try: invite = TeamInviteSurrogate(invite_id) except Team.DoesNotExist: return redirect("/") organization = cast(Organization, invite.organization) user = request.user if request.method == "POST": if request.user.is_authenticated: user = cast(User, request.user) try: invite.use(user) except ValueError as e: return render_template( "signup_to_organization.html", request=request, context={ "user": user, "custom_error": str(e), "organization": organization, "invite_id": invite_id, }, ) else: posthoganalytics.capture( user.distinct_id, "user joined from invite", properties={"organization_id": organization.id}, ) return redirect("/") else: email = request.POST["email"] password = request.POST["password"] first_name = request.POST.get("name") email_opt_in = request.POST.get("emailOptIn") == "on" valid_inputs = (is_input_valid("name", first_name) and is_input_valid("email", email) and is_input_valid("password", password)) already_exists = User.objects.filter(email=email).exists() custom_error = None try: invite.validate(user=None, email=email) except ValueError as e: custom_error = str(e) if already_exists or not valid_inputs or custom_error: return render_template( "signup_to_organization.html", request=request, context={ "email": email, "name": first_name, "already_exists": already_exists, "custom_error": custom_error, "invalid_input": not valid_inputs, "organization": organization, "invite_id": invite_id, }, ) user = User.objects.create_user(email, password, first_name=first_name, email_opt_in=email_opt_in) invite.use(user, prevalidated=True) login(request, user, backend="django.contrib.auth.backends.ModelBackend") report_user_signed_up( user.distinct_id, is_instance_first_user=False, is_organization_first_user=False, new_onboarding_enabled=( not organization.setup_section_2_completed), backend_processor="signup_to_organization_view", ) return redirect("/") return render_template( "signup_to_organization.html", request, context={ "organization": organization, "user": user, "invite_id": invite_id }, )
def social_create_user(strategy: DjangoStrategy, details, backend, request, user=None, *args, **kwargs): if user: return {"is_new": False} user_email = details["email"][0] if isinstance( details["email"], (list, tuple)) else details["email"] user_name = details["fullname"] strategy.session_set("user_name", user_name) strategy.session_set("backend", backend.name) from_invite = False invite_id = strategy.session_get("invite_id") if not invite_id: organization_name = strategy.session_get("organization_name", None) email_opt_in = strategy.session_get("email_opt_in", None) if not organization_name or email_opt_in is None: return redirect(finish_social_signup) serializer = OrganizationSignupSerializer( data={ "organization_name": organization_name, "email_opt_in": email_opt_in, "first_name": user_name, "email": user_email, "password": None, }, context={"request": request}, ) serializer.is_valid(raise_exception=True) user = serializer.save() else: from_invite = True try: invite: Union[ OrganizationInvite, TeamInviteSurrogate] = OrganizationInvite.objects.select_related( "organization", ).get(id=invite_id) except (OrganizationInvite.DoesNotExist, ValidationError): try: invite = TeamInviteSurrogate(invite_id) except Team.DoesNotExist: return redirect( f"/signup/{invite_id}?error_code=invalid_invite&source=social_create_user" ) try: invite.validate(user=None, email=user_email) except exceptions.ValidationError as e: return redirect( f"/signup/{invite_id}?error_code={e.get_codes()[0]}&error_detail={e.args[0]}&source=social_create_user" ) try: user = strategy.create_user(email=user_email, first_name=user_name, password=None) except Exception as e: capture_exception(e) message = "Account unable to be created. This account may already exist. Please try again" " or use different credentials." return redirect( f"/signup/{invite_id}?error_code=unknown&error_detail={message}&source=social_create_user" ) invite.use(user, prevalidated=True) report_user_signed_up( distinct_id=user.distinct_id, is_instance_first_user=User.objects.count() == 1, is_organization_first_user=not from_invite, new_onboarding_enabled=False, backend_processor="social_create_user", social_provider=backend.name, ) return {"is_new": True, "user": user}
def social_create_user(strategy: DjangoStrategy, details, backend, request, user=None, *args, **kwargs): if user: return {"is_new": False} backend_processor = "social_create_user" user_email = details["email"][0] if isinstance(details["email"], (list, tuple)) else details["email"] user_name = ( details["fullname"] or f"{details['first_name'] or ''} {details['last_name'] or ''}".strip() or details["username"] ) strategy.session_set("user_name", user_name) strategy.session_set("backend", backend.name) from_invite = False invite_id = strategy.session_get("invite_id") if not user_email or not user_name: missing_attr = "email" if not user_email else "name" raise ValidationError( {missing_attr: "This field is required and was not provided by the IdP."}, code="required" ) if invite_id: from_invite = True user = process_social_invite_signup(strategy, invite_id, user_email, user_name) else: # Domain whitelist? user = process_social_domain_whitelist_signup(user_email, user_name) if user: backend_processor = "domain_whitelist" # SAML if not user: user = process_social_saml_signup(backend, user_email, user_name) if user: backend_processor = "saml" if not user: organization_name = strategy.session_get("organization_name", None) email_opt_in = strategy.session_get("email_opt_in", None) if not organization_name or email_opt_in is None: return redirect(finish_social_signup) serializer = SignupSerializer( data={ "organization_name": organization_name, "email_opt_in": email_opt_in, "first_name": user_name, "email": user_email, "password": None, }, context={"request": request}, ) serializer.is_valid(raise_exception=True) user = serializer.save() report_user_signed_up( user, is_instance_first_user=User.objects.count() == 1, is_organization_first_user=not from_invite, new_onboarding_enabled=False, backend_processor=backend_processor, social_provider=backend.name, user_analytics_metadata=user.get_analytics_metadata(), org_analytics_metadata=user.organization.get_analytics_metadata() if user.organization else None, ) return {"is_new": True, "user": user}
def social_create_user(strategy: DjangoStrategy, details, backend, request, user=None, *args, **kwargs): if user: return {"is_new": False} user_email = details["email"][0] if isinstance( details["email"], (list, tuple)) else details["email"] user_name = details["fullname"] strategy.session_set("user_name", user_name) strategy.session_set("backend", backend.name) from_invite = False invite_id = strategy.session_get("invite_id") if not invite_id: company_name = strategy.session_get("company_name", None) email_opt_in = strategy.session_get("email_opt_in", None) if not company_name or email_opt_in is None: return redirect(finish_social_signup) serializer = OrganizationSignupSerializer( data=dict( company_name=company_name, email_opt_in=email_opt_in, first_name=user_name, email=user_email, password=None, ), context={"request": request}, ) serializer.is_valid(raise_exception=True) user = serializer.save() else: from_invite = True try: invite: Union[ OrganizationInvite, TeamInviteSurrogate] = OrganizationInvite.objects.select_related( "organization", ).get(id=invite_id) except (OrganizationInvite.DoesNotExist, ValidationError): try: invite = TeamInviteSurrogate(invite_id) except Team.DoesNotExist: processed = render_to_string( "auth_error.html", {"message": "Invalid invite link!"}, ) return HttpResponse(processed, status=401) try: invite.validate(user=None, email=user_email) except ValueError as e: processed = render_to_string( "auth_error.html", {"message": str(e)}, ) return HttpResponse(processed, status=401) try: user = strategy.create_user(email=user_email, first_name=user_name, password=None) except Exception as e: capture_exception(e) processed = render_to_string( "auth_error.html", { "message": "Account unable to be created. This account may already exist. Please try again or use different credentials!" }, ) return HttpResponse(processed, status=401) invite.use(user, prevalidated=True) report_user_signed_up( distinct_id=user.distinct_id, is_instance_first_user=User.objects.count() == 1, is_organization_first_user=not from_invite, new_onboarding_enabled=False, backend_processor="social_create_user", social_provider=backend.name, ) return {"is_new": True, "user": user}
def social_create_user(strategy: DjangoStrategy, details, backend, request, user=None, *args, **kwargs): if user: return {"is_new": False} backend_processor = "social_create_user" user_email = details["email"][0] if isinstance( details["email"], (list, tuple)) else details["email"] user_name = details["fullname"] or details["username"] strategy.session_set("user_name", user_name) strategy.session_set("backend", backend.name) from_invite = False invite_id = strategy.session_get("invite_id") if not invite_id: domain_organization: Optional[Organization] = None # TODO: This feature is currently available only in self-hosted if not settings.MULTI_TENANCY: # Check if the user is on a whitelisted domain domain = user_email.split("@")[-1] # TODO: Handle multiple organizations with the same whitelisted domain domain_organization = Organization.objects.filter( domain_whitelist__contains=[domain]).first() if domain_organization: backend_processor = "domain_whitelist" user = User.objects.create_and_join( organization=domain_organization, email=user_email, password=None, first_name=user_name) else: organization_name = strategy.session_get("organization_name", None) email_opt_in = strategy.session_get("email_opt_in", None) if not organization_name or email_opt_in is None: return redirect(finish_social_signup) serializer = SignupSerializer( data={ "organization_name": organization_name, "email_opt_in": email_opt_in, "first_name": user_name, "email": user_email, "password": None, }, context={"request": request}, ) serializer.is_valid(raise_exception=True) user = serializer.save() else: from_invite = True try: invite: Union[ OrganizationInvite, TeamInviteSurrogate] = OrganizationInvite.objects.select_related( "organization", ).get(id=invite_id) except (OrganizationInvite.DoesNotExist, ValidationError): try: invite = TeamInviteSurrogate(invite_id) except Team.DoesNotExist: return redirect( f"/signup/{invite_id}?error_code=invalid_invite&source=social_create_user" ) try: invite.validate(user=None, email=user_email) except exceptions.ValidationError as e: return redirect( f"/signup/{invite_id}?error_code={e.get_codes()[0]}&error_detail={e.args[0]}&source=social_create_user" ) try: user = strategy.create_user(email=user_email, first_name=user_name, password=None) except Exception as e: capture_exception(e) message = "Account unable to be created. This account may already exist. Please try again" " or use different credentials." return redirect( f"/signup/{invite_id}?error_code=unknown&error_detail={message}&source=social_create_user" ) invite.use(user, prevalidated=True) report_user_signed_up( distinct_id=user.distinct_id, is_instance_first_user=User.objects.count() == 1, is_organization_first_user=not from_invite, new_onboarding_enabled=False, backend_processor=backend_processor, social_provider=backend.name, ) return {"is_new": True, "user": user}