示例#1
0
def debug_random_login(request):
    if not settings.DEBUG:
        raise AccessDenied(title="Эта фича доступна только при DEBUG=true")

    slug = "random_" + random_string()
    user, is_created = User.objects.get_or_create(
        slug=slug,
        defaults=dict(
            patreon_id=random_string(),
            membership_platform_type=User.MEMBERSHIP_PLATFORM_PATREON,
            email=slug + "@random.dev",
            full_name="%s %d y.o. Developer" % (random.choice(["Максим", "Олег"]), random.randint(18, 101)),
            company="Acme Corp.",
            position=random.choice(["Подниматель пингвинов", "Опускатель серверов", "Коллектор пивных бутылок"]),
            balance=10000,
            membership_started_at=datetime.utcnow(),
            membership_expires_at=datetime.utcnow() + timedelta(days=365 * 100),
            created_at=datetime.utcnow(),
            updated_at=datetime.utcnow(),
            is_email_verified=True,
            moderation_status=User.MODERATION_STATUS_APPROVED,
        ),
    )

    if is_created:
        Post.upsert_user_intro(user, "Интро как интро, аппрув прошло :Р", is_visible=True)

    session = Session.create_for_user(user)

    return set_session_cookie(redirect("profile", user.slug), user, session)
示例#2
0
 def create_for_user(cls, user):
     return Session.objects.create(
         user=user,
         token=random_string(length=32),
         created_at=datetime.utcnow(),
         expires_at=max(user.membership_expires_at, datetime.utcnow() + timedelta(days=30)),
     )
示例#3
0
    def save(self, *args, **kwargs):
        if not self.secret_hash:
            self.secret_hash = random_string(length=10)

        if not self.slug:
            self.slug = generate_unique_slug(User, self.full_name, separator="")

        self.updated_at = datetime.utcnow()
        return super().save(*args, **kwargs)
示例#4
0
def delete_user_data(user: User):
    if user.deleted_at is None:
        # user changed his mind
        return

    old_slug = str(user.slug)

    # anonymize user
    user.slug = random_string(length=32)
    user.email = f"{user.slug}@deleted.com"
    user.is_email_unsubscribed = True
    user.is_email_verified = False
    user.moderation_status = User.MODERATION_STATUS_REJECTED
    user.full_name = "💀 Юзер Удалился"
    user.avatar = None
    user.company = None
    user.position = None
    user.city = None
    user.country = None
    user.geo = None
    user.bio = None
    user.contact = None
    user.email_digest_type = User.EMAIL_DIGEST_TYPE_NOPE
    user.telegram_id = None
    user.telegram_data = None
    user.membership_platform_data = None
    user.save()

    # delete intro
    Post.objects.filter(author=user, type=Post.TYPE_INTRO).delete()

    # delete draft and unpublished posts
    Post.objects.filter(author=user, is_visible=False).delete()

    # transfer visible post ownership to "@deleted" user
    deleted_user = User.objects.filter(slug=settings.DELETED_USERNAME).first()
    if deleted_user:
        Post.objects.filter(author=user,
                            is_visible=True).update(author=deleted_user)

    # replace nickname in replies
    new_slug = str(user.slug)
    Comment.objects\
        .filter(reply_to__isnull=False, text__contains=f"@{old_slug}")\
        .update(
            text=Replace("text", Value(f"@{old_slug}"), Value(f"@{new_slug}")),
            html=None
        )

    # drop related data
    UserAchievement.objects.filter(user=user).delete()
    UserTag.objects.filter(user=user).delete()
    UserExpertise.objects.filter(user=user).delete()
    Session.objects.filter(user=user).delete()
    Code.objects.filter(user=user).delete()
    PostBookmark.objects.filter(user=user).delete()
示例#5
0
def generate_unique_slug(model, name, separator="-"):
    attempts = 5
    while attempts > 0:
        slug = slugify(name[:30], separator=separator)
        is_exists = model.objects.filter(slug__iexact=slug).exists()
        if not is_exists:
            return slug
        attempts -= 1
        name += random_string(length=2)
    return str(uuid4())
示例#6
0
 def save(self):
     redis_key = 'suggestion:%s' % random_string()
     data = {
         'account_id': self.account_id,
         'image_url': self.image_url,
         'name': self.name,
         'replacement': self.replacement,
         'count': self.count,
     }
     redis_client.set(redis_key, json.dumps(data))
     self.redis_key = redis_key
示例#7
0
def delete_user_data(user: User):
    if user.deleted_at is None:
        # user changed his mind
        return

    # anonymize user
    user.slug = random_string(length=32)
    user.email = f"{user.slug}@deleted.com"
    user.is_email_unsubscribed = True
    user.is_email_verified = False
    user.moderation_status = User.MODERATION_STATUS_REJECTED
    user.full_name = "💀 Юзер Удалился"
    user.avatar = None
    user.company = None
    user.position = None
    user.city = None
    user.country = None
    user.geo = None
    user.bio = None
    user.contact = None
    user.email_digest_type = User.EMAIL_DIGEST_TYPE_NOPE
    user.telegram_id = None
    user.telegram_data = None
    user.membership_platform_data = None
    user.save()

    # delete intro
    Post.objects.filter(author=user, type=Post.TYPE_INTRO).delete()

    # delete draft posts
    Post.objects.filter(author=user, is_visible=False).delete()

    # drop related data
    UserAchievement.objects.filter(user=user).delete()
    UserTag.objects.filter(user=user).delete()
    UserExpertise.objects.filter(user=user).delete()
    Session.objects.filter(user=user).delete()
    Code.objects.filter(user=user).delete()
    PostBookmark.objects.filter(user=user).delete()

    # cancel stripe subscriptions
    if user.stripe_id:
        stripe_subscriptions = stripe.Subscription.list(
            customer=user.stripe_id, limit=100)
        subscription_ids = [s["id"] for s in stripe_subscriptions["data"]]

        for subscription_id in subscription_ids:
            try:
                stripe.Subscription.delete(subscription_id)
            except Exception:
                pass
示例#8
0
def debug_dev_login(request):
    if not settings.DEBUG:
        raise AccessDenied(title="Эта фича доступна только при DEBUG=true")

    user, is_created = User.objects.get_or_create(
        slug="dev",
        defaults=dict(
            membership_platform_type=User.MEMBERSHIP_PLATFORM_PATREON,
            membership_platform_id="DUMMY",
            email="*****@*****.**",
            full_name="Senior 23 y.o. Developer",
            company="FAANG",
            position="Team Lead конечно",
            balance=10000,
            membership_started_at=datetime.utcnow(),
            membership_expires_at=datetime.utcnow() +
            timedelta(days=365 * 100),
            created_at=datetime.utcnow(),
            updated_at=datetime.utcnow(),
            is_email_verified=True,
            is_profile_complete=True,
            is_profile_reviewed=True,
            is_profile_rejected=False,
            roles=["god"],
        ),
    )

    if is_created:
        Post.upsert_user_intro(user, "Очень плохое интро", is_visible=True)

    session = Session.objects.create(
        user=user,
        token=random_string(length=32),
        created_at=datetime.utcnow(),
        expires_at=datetime.utcnow() + timedelta(days=365 * 100),
    )

    response = redirect("profile", user.slug)
    response.set_cookie(
        key="token",
        value=session.token,
        max_age=settings.SESSION_COOKIE_AGE,
        httponly=True,
        secure=False,
    )
    return response
示例#9
0
def patreon_oauth_callback(request):
    code = request.GET.get("code")
    if not code:
        return render(
            request, "error.html", {
                "title": "Что-то сломалось между нами и патреоном",
                "message": "Так бывает. Попробуйте залогиниться еще раз"
            })

    try:
        auth_data = patreon.fetch_auth_data(code)
        user_data = patreon.fetch_user_data(auth_data["access_token"])
    except PatreonException as ex:
        if "invalid_grant" in str(ex):
            return render(
                request, "error.html", {
                    "title":
                    "Тут такое дело 😭",
                    "message":
                    "Авторизация патреона — говно. "
                    "Она не сразу понимает, что вы стали патроном и отдаёт "
                    "статус «отказано» в первые несколько минут, а иногда и часов. "
                    "Я уже написал им в саппорт, но пока вам надо немного подождать и авторизоваться снова. "
                    "Если долго не будет пускать — напишите мне в личку на патреоне."
                })

        return render(
            request, "error.html", {
                "message":
                "Не получилось загрузить ваш профиль с серверов патреона. "
                "Попробуйте еще раз, наверняка оно починится. "
                f"Но если нет, то вот текст ошибки, с которым можно пожаловаться мне в личку:",
                "data":
                str(ex)
            })

    membership = patreon.parse_active_membership(user_data)
    if not membership:
        return render(
            request, "error.html", {
                "title":
                "Надо быть патроном, чтобы состоять в Клубе",
                "message":
                "Кажется, вы не патроните <a href=\"https://www.patreon.com/join/vas3k\">@vas3k</a>. "
                "А это одно из основных требований для входа в Клуб.<br><br>"
                "Ещё иногда бывает, что ваш банк отказывает патреону в снятии денег. "
                "Проверьте, всё ли там у них в порядке."
            })

    now = datetime.utcnow()
    user, is_created = User.objects.get_or_create(
        membership_platform_type=User.MEMBERSHIP_PLATFORM_PATREON,
        membership_platform_id=membership.user_id,
        defaults=dict(
            email=membership.email,
            full_name=membership.full_name[:120],
            avatar=upload_image_from_url(membership.image)
            if membership.image else None,
            membership_started_at=membership.started_at,
            membership_expires_at=membership.expires_at,
            created_at=now,
            updated_at=now,
            is_email_verified=False,
            is_profile_complete=False,  # redirect new users to an intro page
        ),
    )

    if is_created:
        user.balance = membership.lifetime_support_cents / 100
    else:
        user.membership_expires_at = membership.expires_at
        user.balance = membership.lifetime_support_cents / 100  # TODO: remove when the real money comes in

    user.membership_platform_data = {
        "access_token": auth_data["access_token"],
        "refresh_token": auth_data["refresh_token"],
    }
    user.save()

    session = Session.objects.create(
        user=user,
        token=random_string(length=32),
        created_at=now,
        expires_at=user.membership_expires_at,
    )

    redirect_to = reverse("profile", args=[user.slug])

    state = request.GET.get("state")
    if state:
        redirect_to += f"?{state}"

    response = redirect(redirect_to)
    response.set_cookie(
        key="token",
        value=session.token,
        max_age=settings.SESSION_COOKIE_AGE,
        httponly=True,
        secure=not settings.DEBUG,
    )
    return response
示例#10
0
def patreon_oauth_callback(request):
    code = request.GET.get("code")
    if not code:
        return render(
            request, "error.html", {
                "message":
                "Что-то сломалось между нами и патреоном. Так бывает. Попробуйте залогиниться еще раз."
            })

    try:
        auth_data = patreon.fetch_auth_data(code)
        user_data = patreon.fetch_user_data(auth_data["access_token"])
    except PatreonException as ex:
        if "invalid_grant" in str(ex):
            return render(
                request, "error.html", {
                    "message":
                    "Тут такое дело. Авторизация патреона — говно. "
                    "Она не сразу понимает, что вы стали моим патроном и отдаёт мне ошибку. "
                    "Я уже написал им в саппорт, но пока вам надо немного подождать и авторизоваться снова. "
                    "Обычно тогда срабатывает. Если нет — напишите мне в личные сообщения на патреоне."
                })

        return render(
            request, "error.html", {
                "message":
                "Не получилось загрузить ваш профиль с серверов патреона. "
                "Попробуйте еще раз, наверняка оно починится. "
                f"Но если нет, то вот текст ошибки, с которым можно пожаловаться мне в личку:",
                "data":
                str(ex)
            })

    membership = patreon.parse_active_membership(user_data)
    if not membership:
        return render(
            request, "error.html", {
                "message":
                "Надо быть патроном чтобы состоять в клубе.<br>"
                '<a href="https://www.patreon.com/join/vas3k">Станьте им здесь!</a>'
            })

    now = datetime.utcnow()
    user, is_created = User.objects.get_or_create(
        membership_platform_type=User.MEMBERSHIP_PLATFORM_PATREON,
        membership_platform_id=membership.user_id,
        defaults=dict(
            email=membership.email,
            full_name=membership.full_name[:120],
            avatar=upload_image_from_url(membership.image)
            if membership.image else None,
            membership_started_at=membership.started_at,
            membership_expires_at=membership.expires_at,
            created_at=now,
            updated_at=now,
            is_email_verified=False,
            is_profile_complete=False,  # redirect new users to an intro page
        ),
    )

    if is_created:
        user.balance = membership.lifetime_support_cents / 100
    else:
        user.membership_expires_at = membership.expires_at
        user.balance = membership.lifetime_support_cents / 100  # TODO: remove when the real money comes in

    user.membership_platform_data = {
        "access_token": auth_data["access_token"],
        "refresh_token": auth_data["refresh_token"],
    }
    user.save()

    session = Session.objects.create(
        user=user,
        token=random_string(length=32),
        created_at=now,
        expires_at=first_day_of_next_month(now),
    )

    redirect_to = reverse("profile", args=[user.slug])

    state = request.GET.get("state")
    if state:
        redirect_to += f"?{state}"

    response = redirect(redirect_to)
    response.set_cookie(
        key="token",
        value=session.token,
        max_age=settings.SESSION_COOKIE_AGE,
        httponly=True,
        secure=not settings.DEBUG,
    )
    return response