TGViewer
C# Short Posts 🔞 C# Short Posts 🔞 @dimasshortposts · 306 subscribers
Post #308 620
Так вот, прилетела задачка – сделать для базы знаний подписочную модель.

В Додо это первый случай, когда мы продаём часть системы как услугу для франчайзи. Стоимость Додо ИС входит в роялти. Но тут как бы мы продаём допфункции в приложении, которые не часть кор-функционала. Так что можно накрутить подписку.

Ну и в моей карьере это тоже первый раз, когда мне нужно реализовать чёт такое.

Посему встала задача написать какой-то удобный код, который бы проверял подписку и включал/отключал функционал в зависимости от состояния подписки.

Для себя выделил два типа проблемы, которые нужно решить:

1️⃣ Доступ к определённым функциям по подписке. Если подписка есть — то можно дёрнуть эндпоинт, а если нет, то дёргать нельзя.

2️⃣ Модификация какой-то функции в зависимости от состояния подписки. К примеру, если подписка есть, то возвращаем один список сущностей, а если нет, то обрезанный вариант.

С первым флоу всё просто.

Пишем атрибут и миддлварь, которые делают что-то такое:


public class SubscriptionRequirementAttribute : Attribute, IAuthorizationFilter
{
private readonly string _requiredLevel;

public SubscriptionRequirementAttribute(string requiredLevel)
{
_requiredLevel = requiredLevel;
}

public void OnAuthorization(AuthorizationFilterContext context)
{
var user = context.HttpContext.User;
var hasSubscription = user.HasClaim("SubscriptionLevel", _requiredLevel);

if (!hasSubscription)
{
context.Result = new ForbidResult();
}
}
}

[SubscriptionRequirement("Premium")]
public IActionResult GetPremiumContent()
{
// Доступно только для пользователей с подпиской "Premium"
}


И вуаля. Всё закрыто.

А вот со вторым я пока что размышляю, ибо тут есть несколько вариантов:

Во-первых, всё можно просто заифать. Типа прям в коде юзкейса как-то так:


[HttpGet("data")]
public IActionResult GetData()
{
var baseData = GetBaseData();

if (_subscriptionService.HasSubscription("Premium"))
{
var premiumData = GetPremiumData();
return Ok(new { Base = baseData, Premium = premiumData });
}

return Ok(new { Base = baseData });
}


Ну или сделать какой-то fabric, который выдаёт нужный функционал. Но это уже сорта одного и того же ифинга.
More from @dimasshortposts
  1. Sep 26, 2026🧵 Тредик для вопросов по докладу про MAF на дотнексте В докладе многие подробности опусти…
  2. Sep 23, 2026Даже самым хардкорным ребятам надо отдыхать, так что отдыхаем, мои чюваки 🕺 🧑‍💻dp🥁 #he…
  3. Sep 16, 2026🎯 Instrumented Tier0: профилирование кода В прошлый раз мы разобрали два уровня компиляци…
  4. Sep 15, 2026🔜 Готовлюсь к DOTNEXT 2026 В прошлом году за две недели до выступления я зачитывал свой д…
  5. Sep 9, 2026C# Short Posts 🔞 pinned «🐸 О чём этот канал? Кажется, я уже достаточно давно веду этот к…
  6. Sep 9, 2026🐸 О чём этот канал? Кажется, я уже достаточно давно веду этот канальчик, и пора бы описат…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →