Безопасная multi-tenancy в Lino

Multi-tenancy позволяСт ΠΎΠ΄Π½ΠΎΠΌΡƒ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡŽ ΠΎΠ±ΡΠ»ΡƒΠΆΠΈΠ²Π°Ρ‚ΡŒ Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… ΠΊΠ»ΠΈΠ΅Π½Ρ‚ΠΎΠ², ΠΊΠΎΠΌΠΏΠ°Π½ΠΈΠΈ ΠΈΠ»ΠΈ ΠΎΡ€Π³Π°Π½ΠΈΠ·Π°Ρ†ΠΈΠΈ, сохраняя Π΄Π°Π½Π½Ρ‹Π΅ ΠΈ Ρ€Π°Π·Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ ΠΈΠ·ΠΎΠ»ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹ΠΌΠΈ. Π’ Lino Tenant рассматриваСтся ΠΊΠ°ΠΊ Ρ‡Π°ΡΡ‚ΡŒ ΠΏΠΎΡ‚ΠΎΠΊΠ° прилоТСния: функция Π³Π΅Π½Π΅Ρ€ΠΈΡ€ΡƒΠ΅Ρ‚ основу tenancy, опрСдСляСт Tenant ΠΏΠΎ subdomain, host ΠΈΠ»ΠΈ slug Ρ‡Π΅Ρ€Π΅Π· ITenantContext ΠΈ прСдоставляСт ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ, Π°ΡƒΡ‚Π΅Π½Ρ‚ΠΈΡ„ΠΈΡ†ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠ³ΠΎ ΠΏΠΎ JWT, Ρ‡Π΅Ρ€Π΅Π· IUserContext.

JWT Ρ‚Π°ΠΊΠΆΠ΅ содСрТит TenantId, для ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒ Π±Ρ‹Π» Π°ΡƒΡ‚Π΅Π½Ρ‚ΠΈΡ„ΠΈΡ†ΠΈΡ€ΠΎΠ²Π°Π½. Lino сравниваСт этот Tenant с Tenant, ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½Ρ‹ΠΌ для запроса, поэтому эта страница сосрСдоточСна Π½Π° Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ Π½ΡƒΠΆΠ½ΠΎ Ρ€Π΅ΡˆΠΈΡ‚ΡŒ послС появлСния этой основы: ΠΌΠΎΠ΄Π΅Π»ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ сущностСй, Ρ€Π°Π·Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ ΠΏΠΎ организациям ΠΈ ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎΠ΅ использованиС сгСнСрированных абстракций.

Π”ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠΈ Tenant

Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ Tenant, ΠΊΠΎΠ³Π΄Π° систСма являСтся SaaS ΠΈΠ»ΠΈ ΠΊΠΎΠ³Π΄Π° Π΄Π°Π½Π½Ρ‹Π΅ Ρ€Π°Π·Π½Ρ‹Ρ… ΠΊΠ»ΠΈΠ΅Π½Ρ‚ΠΎΠ² Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΡΠΎΡΡƒΡ‰Π΅ΡΡ‚Π²ΠΎΠ²Π°Ρ‚ΡŒ Π² ΠΎΠ΄Π½ΠΎΠΌ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΈ Π±Π΅Π· ΡƒΡ‚Π΅Ρ‡Π΅ΠΊ ΠΌΠ΅ΠΆΠ΄Ρƒ контСкстами.

lino feature tenant add

АссистСнт Π³Π΅Π½Π΅Ρ€ΠΈΡ€ΡƒΠ΅Ρ‚ основу для рСгистрации Tenants, связи ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΉ, опрСдСлСния Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π³ΠΎ Tenant, распространСния Ρ‡Π΅Ρ€Π΅Π· контСкст прилоТСния ΠΈ ΠΈΠ½Ρ‚Π΅Π³Ρ€Π°Ρ†ΠΈΠΈ с Π°ΡƒΡ‚Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ†ΠΈΠ΅ΠΉ. ITenantContext прСдставляСт Tenant, ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½Ρ‹ΠΉ ΠΏΠΎ subdomain, host ΠΈΠ»ΠΈ slug, Π° IUserContext прСдставляСт ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ, Π°ΡƒΡ‚Π΅Π½Ρ‚ΠΈΡ„ΠΈΡ†ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠ³ΠΎ ΠΏΠΎ JWT, Π²ΠΊΠ»ΡŽΡ‡Π°Ρ TenantId, для ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ ΠΎΠ½ Π±Ρ‹Π» Π°ΡƒΡ‚Π΅Π½Ρ‚ΠΈΡ„ΠΈΡ†ΠΈΡ€ΠΎΠ²Π°Π½.

ПослС Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΠΈ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΡŒΡ‚Π΅, ΠΊΠ°ΠΊΠΈΠ΅ сущности Π΄Π΅ΠΉΡΡ‚Π²ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ ΠΏΡ€ΠΈΠ½Π°Π΄Π»Π΅ΠΆΠ°Ρ‚ Tenant, Π° ΠΊΠ°ΠΊΠΈΠ΅ ΡΠ²Π»ΡΡŽΡ‚ΡΡ global. Π­Ρ‚Π° ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° являСтся Ρ‡Π°ΡΡ‚ΡŒΡŽ модСлирования ΠΏΡ€ΠΎΠ΄ΡƒΠΊΡ‚Π°: multi-tenancy β€” это Π½Π΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ созданиС Ρ‚Π°Π±Π»ΠΈΡ†Ρ‹ Tenants, Π½ΠΎ ΠΈ Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅, ΠΊΠ°ΠΊΠΈΠ΅ ΠΏΡ€Π°Π²ΠΈΠ»Π°, экраны, Ρ€Π°Π·Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ, Π΄Π°Π½Π½Ρ‹Π΅ ΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ зависят ΠΎΡ‚ Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π³ΠΎ Tenant, ΠΏΡ€ΠΎΠ²Π΅Ρ€Π΅Π½Π½ΠΎΠ³ΠΎ Lino.

  • Tenant-scoped: Π·Π°ΠΊΠ°Π·Ρ‹, ΠΏΡ€ΠΎΠ΄ΡƒΠΊΡ‚Ρ‹ ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π°, настройки ΠΊΠΎΠΌΠΏΠ°Π½ΠΈΠΈ, ΠΊΠ»ΠΈΠ΅Π½Ρ‚Ρ‹ CRM ΠΈΠ»ΠΈ Π»ΡŽΠ±Ρ‹Π΅ Π΄Π°Π½Π½Ρ‹Π΅, ΠΏΡ€ΠΈΠ½Π°Π΄Π»Π΅ΠΆΠ°Ρ‰ΠΈΠ΅ ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΠΎΠΉ ΠΎΡ€Π³Π°Π½ΠΈΠ·Π°Ρ†ΠΈΠΈ.
  • Global: ΠΏΡƒΠ±Π»ΠΈΡ‡Π½Ρ‹ΠΉ ΠΊΠ°Ρ‚Π°Π»ΠΎΠ³ ΠΏΠ»Π°Ρ‚Ρ„ΠΎΡ€ΠΌΡ‹, ΠΏΠ»Π°Π½Ρ‹, Π²Π½ΡƒΡ‚Ρ€Π΅Π½Π½ΠΈΠ΅ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΎΠ½Π½Ρ‹Π΅ рСсурсы, административныС настройки ΠΈΠ»ΠΈ Π΄Π°Π½Π½Ρ‹Π΅, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹Π΅ Π΄ΠΎ Π²Ρ‹Π±ΠΎΡ€Π° Tenant.
  • Hybrid: global Π΄Π°Π½Π½Ρ‹Π΅ с настройкой ΠΏΠΎ Tenant, Ρ‚Ρ€Π΅Π±ΡƒΡŽΡ‰ΠΈΠ΅ явного модСлирования, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΈΠ·Π±Π΅ΠΆΠ°Ρ‚ΡŒ Π½Π΅ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎΠ³ΠΎ дублирования ΠΈΠ»ΠΈ ΡƒΡ‚Π΅Ρ‡ΠΊΠΈ ΠΏΡ€Π°Π²ΠΈΠ».

Π’ ΠΌΠΎΠ΄ΡƒΠ»ΡŒΠ½ΠΎΠΌ ΠΌΠΎΠ½ΠΎΠ»ΠΈΡ‚Π΅ ΠΌΠΎΠ΄ΡƒΠ»ΡŒ tenancy ΠΎΠ±Ρ‹Ρ‡Π½ΠΎ являСтся Π²Π»Π°Π΄Π΅Π»ΡŒΡ†Π΅ΠΌ исходной сущности Tenant. Π”Ρ€ΡƒΠ³ΠΈΠ΅ ΠΌΠΎΠ΄ΡƒΠ»ΠΈ, Ρ‚Π°ΠΊΠΈΠ΅ ΠΊΠ°ΠΊ catalog ΠΈΠ»ΠΈ CRM, Π½Π΅ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΠΎΠ±Ρ€Π°Ρ‰Π°Ρ‚ΡŒΡΡ ΠΊ этой сущности Π½Π°ΠΏΡ€ΡΠΌΡƒΡŽ. Когда ΠΈΠΌ Π½ΡƒΠΆΠ½ΠΎ Π·Π½Π°Ρ‚ΡŒ Tenant, ΠΎΠ½ΠΈ ΠΌΠΎΠ³ΡƒΡ‚ Ρ…Ρ€Π°Π½ΠΈΡ‚ΡŒ shadow entities с минимально Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹ΠΌΠΈ полями, наполняСмыС integration events, Ρ‚Π°ΠΊΠΈΠΌΠΈ ΠΊΠ°ΠΊ созданиС ΠΈΠ»ΠΈ ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΠ΅ Tenant.

Tenant context

Π‘ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠ΅ΠΉ Tenant Lino Ρ†Π΅Π½Ρ‚Ρ€Π°Π»ΠΈΠ·ΡƒΠ΅Ρ‚ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π³ΠΎ Tenant ΠΈ прСдоставляСт это Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Ρ‡Π΅Ρ€Π΅Π· ITenantContext. Π­Ρ‚ΠΎΡ‚ контСкст прСдставляСт Tenant, ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½Ρ‹ΠΉ ΠΈΠ· subdomain, host ΠΈΠ»ΠΈ slug запроса, Π²ΠΊΠ»ΡŽΡ‡Π°Ρ свСдСния Π²Ρ€ΠΎΠ΄Π΅ TenantId ΠΈ slug, ΠΊΠΎΠ³Π΄Π° Tenant Π½Π°ΠΉΠ΄Π΅Π½.

Π’ Π°ΡƒΡ‚Π΅Π½Ρ‚ΠΈΡ„ΠΈΡ†ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹Ρ… ΠΏΠΎΡ‚ΠΎΠΊΠ°Ρ… IUserContext Ρ‡ΠΈΡ‚Π°Π΅Ρ‚ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ ΠΈΠ· JWT. Π­Ρ‚ΠΎΡ‚ JWT Ρ‚Π°ΠΊΠΆΠ΅ содСрТит TenantId, для ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒ Π±Ρ‹Π» Π°ΡƒΡ‚Π΅Π½Ρ‚ΠΈΡ„ΠΈΡ†ΠΈΡ€ΠΎΠ²Π°Π½. Lino сравниваСт Tenant ΠΈΠ· IUserContext с Tenant ΠΈΠ· ITenantContext, прСдотвращая Π΄ΠΎΠ²Π΅Ρ€ΠΈΠ΅ бизнСс-ΠΏΡ€Π°Π²ΠΈΠ» расходящимся контСкстам.

Π’ сгСнСрированных ΠΈΠ»ΠΈ Π΄ΠΎΠ±Π°Π²Π»Π΅Π½Π½Ρ‹Ρ… ΠΏΠΎΠ·ΠΆΠ΅ функциях всСгда ΠΏΡ€Π΅Π΄ΠΏΠΎΡ‡ΠΈΡ‚Π°ΠΉΡ‚Π΅ эти абстракции вмСсто ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΠΎΠ³ΠΎ Ρ€ΡƒΡ‡Π½ΠΎΠ³ΠΎ чтСния claims ΠΈΠ»ΠΈ получСния ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ»ΡŒΠ½ΠΎΠ³ΠΎ TenantId Π² ΠΊΠ°ΠΆΠ΄ΠΎΠΌ handler. Π­Ρ‚ΠΎ сохраняСт commands, queries, страницы ΠΈ ΠΈΠ½Ρ‚Π΅Π³Ρ€Π°Ρ†ΠΈΠΈ Π½Π° ΠΎΠ΄Π½ΠΎΠΉ source of truth ΠΈ сохраняСт ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌΡ‹ бСзопасности, ΡƒΠΆΠ΅ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½Π½Ρ‹Π΅ Lino.

Background Jobs, ΠΏΠΎΡ‚Ρ€Π΅Π±ΠΈΡ‚Π΅Π»ΠΈ событий ΠΈ ΠΈΠ½Ρ‚Π΅Π³Ρ€Π°Ρ†ΠΈΠΈ Ρ‚Π°ΠΊΠΆΠ΅ Π½ΡƒΠΆΠ΄Π°ΡŽΡ‚ΡΡ Π² контСкстС. Job, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π΅Ρ‚ tenant-scoped ΠΏΡ€ΠΎΠ΄ΡƒΠΊΡ‚Ρ‹, ΠΊΠ»ΠΈΠ΅Π½Ρ‚ΠΎΠ² ΠΈΠ»ΠΈ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΉ, Π΄ΠΎΠ»ΠΆΠ΅Π½ явно ΠΏΠΎΠ»ΡƒΡ‡Π°Ρ‚ΡŒ, ΠΊΠ°ΠΊΠΎΠΉ Tenant обрабатываСтся, ΠΏΠΎΡ‚ΠΎΠΌΡƒ Ρ‡Ρ‚ΠΎ Π½Π΅Ρ‚ Π°ΠΊΡ‚ΠΈΠ²Π½ΠΎΠ³ΠΎ HTTP-запроса, ΠΈΠ· ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ ITenantContext ΠΈ IUserContext ΠΌΠΎΠΆΠ½ΠΎ Π±Ρ‹Π»ΠΎ Π±Ρ‹ автоматичСски вывСсти.

Tenant-scoped сущности

Tenant-scoped сущности содСрТат identifier Tenant ΠΈ ΡƒΡ‡Π°ΡΡ‚Π²ΡƒΡŽΡ‚ Π² query filters. Благодаря этому ΠΎΠ±Ρ‹Ρ‡Π½Ρ‹ΠΉ ΠΏΠΎΡ‚ΠΎΠΊ Π½Π΅ Π΄ΠΎΠ»ΠΆΠ΅Π½ Π²Ρ€ΡƒΡ‡Π½ΡƒΡŽ ΠΏΠΎΠΌΠ½ΠΈΡ‚ΡŒ ΠΎ ΠΏΡ€ΠΈΠΌΠ΅Π½Π΅Π½ΠΈΠΈ TenantId Π²ΠΎ всСх queries; функция Π΄ΠΎΠ»ΠΆΠ½Π° ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΡ€ΠΎΠ²Π΅Ρ€Π΅Π½Π½Ρ‹ΠΉ контСкст ΠΈ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Ρ‹, сгСнСрированныС Lino.

  • Π’ΠΊΠ»ΡŽΡ‡Π°ΠΉΡ‚Π΅ Tenant Π² aggregates, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΏΡ€ΠΈΠ½Π°Π΄Π»Π΅ΠΆΠ°Ρ‚ ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΠΎΠΉ ΠΎΡ€Π³Π°Π½ΠΈΠ·Π°Ρ†ΠΈΠΈ.
  • НастраивайтС индСксы с ΡƒΡ‡Π΅Ρ‚ΠΎΠΌ Tenant ΠΈ часто Π·Π°ΠΏΡ€Π°ΡˆΠΈΠ²Π°Π΅ΠΌΡ‹Ρ… ΠΏΠΎΠ»Π΅ΠΉ.
  • Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ ITenantContext ΠΈ IUserContext Π² commands ΠΈ queries вмСсто получСния Tenant ΠΊΠ°ΠΊ ΠΈΠ·ΠΎΠ»ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠ³ΠΎ источника ΠΏΠΎΠ»Π½ΠΎΠΌΠΎΡ‡ΠΈΠΉ.
  • Π’ imports ΠΈ jobs явно опрСдСляйтС, ΠΊΠ°ΠΊΠΎΠΉ Tenant обрабатываСтся.

Tenant-scoped ΡΡƒΡ‰Π½ΠΎΡΡ‚ΡŒ ΠΏΡ€ΠΈΠ½Π°Π΄Π»Π΅ΠΆΠΈΡ‚ ΠΎΠ΄Π½ΠΎΠΌΡƒ Tenant. Если ΡΡƒΡ‰Π½ΠΎΡΡ‚ΡŒ выглядит Ρ‚Π°ΠΊ, Π±ΡƒΠ΄Ρ‚ΠΎ ΠΏΡ€ΠΈΠ½Π°Π΄Π»Π΅ΠΆΠΈΡ‚ нСскольким Tenants, рассматривайтС это ΠΊΠ°ΠΊ Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ модСлирования: Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ, ΠΎΠ½Π° global, Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ, Π½ΡƒΠΆΠ½Π° копия ΠΏΠΎ Tenant, ΠΈΠ»ΠΈ, Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ, отсутствуСт промСТуточная ΡΡƒΡ‰Π½ΠΎΡΡ‚ΡŒ, ΠΏΡ€Π΅Π΄ΡΡ‚Π°Π²Π»ΡΡŽΡ‰Π°Ρ связь. ΠŸΡ€ΠΎΠ΄ΡƒΠΊΡ‚, ΠΊΠ»ΠΈΠ΅Π½Ρ‚ ΠΈΠ»ΠΈ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒ Ρ‚Π°ΠΊΠΆΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΈΠΌΠ΅Ρ‚ΡŒ Ρ€Π°Π·Π½Ρ‹ΠΉ смысл Π² Ρ€Π°Π·Π½Ρ‹Ρ… модулях; Π² Ρ‚Π°ΠΊΠΈΡ… случаях shadow entity с нСсколькими полями ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½Π΅Π΅, Ρ‡Π΅ΠΌ совмСстноС использованиС исходной сущности.

Π’Π°ΠΊΠΆΠ΅ Ρ€Π°Π·Π»ΠΈΡ‡Π°ΠΉΡ‚Π΅ ссылку ΠΈ ownership. ΠŸΡ€ΠΎΠ΄ΡƒΠΊΡ‚ Π² catalog ΠΌΠΎΠΆΠ΅Ρ‚ ΡΡΡ‹Π»Π°Ρ‚ΡŒΡΡ Π½Π° Tenant, Π½ΠΎ это Π½Π΅ ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ catalog управляСт lifecycle Tenant. ΠœΠΎΠ΄ΡƒΠ»ΡŒ tenancy остаСтся Π²Π»Π°Π΄Π΅Π»ΡŒΡ†Π΅ΠΌ создания, Π°ΠΊΡ‚ΠΈΠ²Π°Ρ†ΠΈΠΈ, Π΄ΠΎΠΌΠ΅Π½Π°, branding ΠΈ Ρ€Π΅ΠΆΠΈΠΌΠ° изоляции; catalog Ρ…Ρ€Π°Π½ΠΈΡ‚ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π΄Π°Π½Π½Ρ‹Π΅, Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹Π΅ для Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Π°Ρ†ΠΈΠΈ ΠΈ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ собствСнного ΠΏΠΎΡ‚ΠΎΠΊΠ°.

  • Π˜Π½Π΄Π΅ΠΊΡΡ‹: ΠΊΠΎΠΌΠ±ΠΈΠ½ΠΈΡ€ΡƒΠΉΡ‚Π΅ TenantId с полями, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹ΠΌΠΈ для поиска, сортировки ΠΈ ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ ΠΏΠΎ Tenant.
  • Commands: примСняйтС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ Π² Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΌ ΠΏΡ€ΠΎΠ²Π΅Ρ€Π΅Π½Π½ΠΎΠΌ Tenant, ΠΊΠΎΠ³Π΄Π° ΡΡƒΡ‰Π½ΠΎΡΡ‚ΡŒ tenant-scoped.
  • Queries: ΡƒΠ΄Π΅Ρ€ΠΆΠΈΠ²Π°ΠΉΡ‚Π΅ ΠΏΠ°Π³ΠΈΠ½Π°Ρ†ΠΈΡŽ, Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Ρ‹ ΠΈ счСтчики Π² Ρ‚ΠΎΠΌ ΠΆΠ΅ контСкстС, ΠΏΡ€ΠΎΠ²Π΅Ρ€Π΅Π½Π½ΠΎΠΌ Lino.
  • Events: Π²ΠΊΠ»ΡŽΡ‡Π°ΠΉΡ‚Π΅ достаточно контСкста, Ρ‡Ρ‚ΠΎΠ±Ρ‹ consumers ΠΌΠΎΠ³Π»ΠΈ ΠΎΠ±Π½ΠΎΠ²Π»ΡΡ‚ΡŒ projections, Π½Π΅ ΠΎΠ±Ρ€Π°Ρ‰Π°ΡΡΡŒ ΠΊ producer Π½Π΅Π½Π°Π΄Π»Π΅ΠΆΠ°Ρ‰ΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ.

Π˜Π·ΠΎΠ»ΡΡ†ΠΈΡ Π΄Π°Π½Π½Ρ‹Ρ…

Π˜Π·ΠΎΠ»ΡΡ†ΠΈΡ ΠΌΠΎΠΆΠ΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒΡΡ ΠΏΠΎ ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ΅, schema ΠΈΠ»ΠΈ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΠΉ Π±Π°Π·Π΅ Π΄Π°Π½Π½Ρ‹Ρ…. Π’Ρ‹Π±ΠΎΡ€ зависит ΠΎΡ‚ стоимости, объСма, Π΄ΠΎΠ³ΠΎΠ²ΠΎΡ€Π½Ρ‹Ρ… Ρ‚Ρ€Π΅Π±ΠΎΠ²Π°Π½ΠΈΠΉ ΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΎΠ½Π½Ρ‹Ρ… возмоТностСй.

Π‘Ρ‚Ρ€Π°Ρ‚Π΅Π³ΠΈΡΠŸΡ€Π΅ΠΈΠΌΡƒΡ‰Π΅ΡΡ‚Π²Π°ΠšΠΎΠ³Π΄Π° ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ
Колонка TenantIdΠŸΡ€ΠΎΡ‰Π΅ ΠΈ дСшСвлСΠ₯ΠΎΡ€ΠΎΡˆΠΈΠΉ Π½Π°Ρ‡Π°Π»ΡŒΠ½Ρ‹ΠΉ Π²Ρ‹Π±ΠΎΡ€ для ΠΌΠ½ΠΎΠ³ΠΈΡ… SaaS, Π² сочСтании с Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Π°ΠΌΠΈ ΠΈ контСкстом Lino.
Schema ΠΏΠΎ TenantΠŸΡ€ΠΎΠΌΠ΅ΠΆΡƒΡ‚ΠΎΡ‡Π½Π°Ρ ΠΈΠ·ΠΎΠ»ΡΡ†ΠΈΡΠŸΠΎΠ»Π΅Π·Π½ΠΎ, ΠΊΠΎΠ³Π΄Π° Π½ΡƒΠΆΠ½Ρ‹ Π±ΠΎΠ»Π΅Π΅ высокиС трСбования ΠΊ Ρ€Π°Π·Π΄Π΅Π»Π΅Π½ΠΈΡŽ Π±Π΅Π· ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄Π° ΠΊ Π±Π°Π·Π΅ Π΄Π°Π½Π½Ρ‹Ρ… ΠΏΠΎ Tenant.
Π‘Π°Π·Π° Π΄Π°Π½Π½Ρ‹Ρ… ΠΏΠΎ TenantБильная ΠΈΠ·ΠΎΠ»ΡΡ†ΠΈΡΠŸΠΎΠ΄Ρ…ΠΎΠ΄ΠΈΡ‚, ΠΊΠΎΠ³Π΄Π° ΠΊΠΎΠ½Ρ‚Ρ€Π°ΠΊΡ‚, объСм ΠΈΠ»ΠΈ эксплуатация ΠΎΠΏΡ€Π°Π²Π΄Ρ‹Π²Π°ΡŽΡ‚ Π±ΠΎΠ»Π΅Π΅ высокиС ΡΡ‚ΠΎΠΈΠΌΠΎΡΡ‚ΡŒ ΠΈ Π°Π²Ρ‚ΠΎΠΌΠ°Ρ‚ΠΈΠ·Π°Ρ†ΠΈΡŽ.

Для Π±ΠΎΠ»ΡŒΡˆΠΈΠ½ΡΡ‚Π²Π° SaaS Π½Π° Ρ€Π°Π½Π½Π΅ΠΉ стадии ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ° ΠΏΠΎ Tenant с global filters ΠΈ Ρ†Π΅Π½Ρ‚Ρ€Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½Π½Ρ‹ΠΌ контСкстом являСтся ΠΏΡ€Π°Π³ΠΌΠ°Ρ‚ΠΈΡ‡Π½ΠΎΠΉ ΠΎΡ‚ΠΏΡ€Π°Π²Π½ΠΎΠΉ Ρ‚ΠΎΡ‡ΠΊΠΎΠΉ. Lino ΠΏΠΎΠΌΠΎΠ³Π°Π΅Ρ‚ с этой основой; ваша ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° Π΄ΠΎΠ»ΠΆΠ½Π° ΠΏΠΎΠ΄Ρ‚Π²Π΅Ρ€Π΄ΠΈΡ‚ΡŒ, Ρ‡Ρ‚ΠΎ tenant-scoped aggregates содСрТат ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½Ρ‹ΠΉ Tenant, Π° Π½ΠΎΠ²Ρ‹Π΅ queries ΠΏΡ€ΠΎΠ΄ΠΎΠ»ΠΆΠ°ΡŽΡ‚ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΉ Tenant, ΠΏΡ€ΠΎΠ²Π΅Ρ€Π΅Π½Π½Ρ‹ΠΉ сгСнСрированными абстракциями.

Π’ ΠΌΠΎΠ΄ΡƒΠ»ΡŒΠ½Ρ‹Ρ… сСрвисах изоляция Tenant ΠΈ изоляция модуля β€” Ρ€Π°Π·Π½Ρ‹Π΅ Π·Π°Π±ΠΎΡ‚Ρ‹. ΠœΠΎΠ΄ΡƒΠ»ΡŒ Catalog ΠΌΠΎΠΆΠ΅Ρ‚ ΠΈΠΌΠ΅Ρ‚ΡŒ Ρ‚Π°Π±Π»ΠΈΡ†Ρƒ ΠΏΡ€ΠΎΠ΄ΡƒΠΊΡ‚ΠΎΠ² с TenantId; ΠΌΠΎΠ΄ΡƒΠ»ΡŒ CRM ΠΌΠΎΠΆΠ΅Ρ‚ ΠΈΠΌΠ΅Ρ‚ΡŒ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ΠΎΠ² с TenantId; Π° ΠΌΠΎΠ΄ΡƒΠ»ΡŒ Tenancy остаСтся Π²Π»Π°Π΄Π΅Π»ΡŒΡ†Π΅ΠΌ исходной рСгистрации Tenants. НаличиС ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΈ Ρ‚ΠΎΠ³ΠΎ ΠΆΠ΅ identifier Π½Π΅ Ρ€Π°Π·Ρ€Π΅ΡˆΠ°Π΅Ρ‚ прямой доступ ΠΌΠ΅ΠΆΠ΄Ρƒ модулями.

Roles ΠΈ Ρ€Π°Π·Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ ΠΏΠΎ Tenant

Π’ SaaS ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ администратором Π² ΠΎΠ΄Π½ΠΎΠΌ Tenant ΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ΠΎΠΌ Π² Π΄Ρ€ΡƒΠ³ΠΎΠΌ. Lino Π³Π΅Π½Π΅Ρ€ΠΈΡ€ΡƒΠ΅Ρ‚ основу для Ρ€Π°Π±ΠΎΡ‚Ρ‹ со связью user-Tenant, Π° Ρ€Π°Π·Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΠΎΡ†Π΅Π½ΠΈΠ²Π°Ρ‚ΡŒΡΡ Π²Π½ΡƒΡ‚Ρ€ΠΈ Π°ΠΊΡ‚ΠΈΠ²Π½ΠΎΠ³ΠΎ контСкста, ΠΏΡ€ΠΎΠ²Π΅Ρ€Π΅Π½Π½ΠΎΠ³ΠΎ framework.

Π’Π°ΠΊΠΆΠ΅ ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‚ административныС Ρ€Π°Π·Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ Π²Π½Π΅ Tenant. Π­ΠΊΡ€Π°Π½ эксплуатации ΠΏΠ»Π°Ρ‚Ρ„ΠΎΡ€ΠΌΡ‹ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ доступСн Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π² систСмном контСкстС, Ρ‚ΠΎΠ³Π΄Π° ΠΊΠ°ΠΊ страницы Π²Ρ€ΠΎΠ΄Π΅ ΠΏΡ€ΠΎΠ΄ΡƒΠΊΡ‚ΠΎΠ² ΠΈ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ΠΎΠ² ΠΌΠΎΠ³ΡƒΡ‚ Ρ‚Ρ€Π΅Π±ΠΎΠ²Π°Ρ‚ΡŒ active Tenant. Π’Π°ΠΊΠΎΠ΅ Ρ€Π°Π·Π΄Π΅Π»Π΅Π½ΠΈΠ΅ ясно ΠΏΠΎΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚, ΠΊΠΎΠ³Π΄Π° дСйствиС являСтся global, Π° ΠΊΠΎΠ³Π΄Π° ΠΎΠ½ΠΎ зависит ΠΎΡ‚ Tenant, ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½ΠΎΠ³ΠΎ Π² ITenantContext, ΠΈ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ, Π°ΡƒΡ‚Π΅Π½Ρ‚ΠΈΡ„ΠΈΡ†ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠ³ΠΎ Π² IUserContext.

  • ΠœΠΎΠ΄Π΅Π»ΠΈΡ€ΡƒΠΉΡ‚Π΅ roles ΠΏΠΎ Tenant, ΠΊΠΎΠ³Π΄Π° Ρ€Π°Π·Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ Ρ€Π°Π·Π»ΠΈΡ‡Π°ΡŽΡ‚ΡΡ ΠΏΠΎ организациям.
  • Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΉ контСкст Π² ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ°Ρ… Π°Π²Ρ‚ΠΎΡ€ΠΈΠ·Π°Ρ†ΠΈΠΈ страниц, commands ΠΈ queries.
  • Π”Π΅Ρ€ΠΆΠΈΡ‚Π΅ claims ΠΊΠΎΠΌΠΏΠ°ΠΊΡ‚Π½Ρ‹ΠΌΠΈ, помСщая Π² token Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ Π΄ΠΎΠ»ΠΆΠ½ΠΎ ΡƒΡ‡Π°ΡΡ‚Π²ΠΎΠ²Π°Ρ‚ΡŒ Π² Π°ΡƒΡ‚Π΅Π½Ρ‚ΠΈΡ„ΠΈΡ†ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠΌ ΠΏΠΎΡ‚ΠΎΠΊΠ΅.
  • ΠžΡ‚Π·Ρ‹Π²Π°ΠΉΡ‚Π΅ ΠΈΠ»ΠΈ обновляйтС tokens ΠΏΡ€ΠΈ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΈ критичСских Ρ€Π°Π·Ρ€Π΅ΡˆΠ΅Π½ΠΈΠΉ.
ΠšΠΎΠ½Ρ‚Π΅ΠΊΡΡ‚ΠŸΡ€ΠΈΠΌΠ΅Ρ€ΠšΠ°ΠΊ ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ‚ΡŒ
SystemАдминистрированиС ΠΏΠ»Π°Ρ‚Ρ„ΠΎΡ€ΠΌΡ‹, ΠΏΠ»Π°Π½Ρ‹, Tenants ΠΈ global настройки.Π’Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒ Π²Π½Π΅ scope ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΠΎΠ³ΠΎ Tenant.
TenantΠŸΡ€ΠΎΠ΄ΡƒΠΊΡ‚Ρ‹, ΠΊΠ»ΠΈΠ΅Π½Ρ‚Ρ‹, Π·Π°ΠΊΠ°Π·Ρ‹, ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΠΈ ΠΈ roles этого Tenant.Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΉ Tenant, ΠΏΡ€ΠΎΠ²Π΅Ρ€Π΅Π½Π½Ρ‹ΠΉ Lino.
BothНСкоторыС Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ identity ΠΈΠ»ΠΈ управлСния, ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠ΅ ΠΈ Π² систСмС, ΠΈ Π² Tenant.Π’ use case явно ΡƒΠΊΠ°Π·Π°Ρ‚ΡŒ, ΠΊΠ°ΠΊΠΎΠΉ контСкст ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ.

JWT ΠΈ Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎΡΡ‚ΡŒ Tenant

Когда функция Tenant Π°ΠΊΡ‚ΠΈΠ²Π½Π°, Lino ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ JWT ΠΊΠ°ΠΊ источник контСкста Π°ΡƒΡ‚Π΅Π½Ρ‚ΠΈΡ„ΠΈΡ†ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠ³ΠΎ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ. IUserContext Ρ‡ΠΈΡ‚Π°Π΅Ρ‚ claims ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ ΠΈ TenantId ΠΈΠ· token, Π½Π΅ прСвращая JWT Π² копию Π±Π°Π·Ρ‹ Π΄Π°Π½Π½Ρ‹Ρ….

  • ΠŸΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°ΠΉΡ‚Π΅ issuer, audience, подпись ΠΈ срок дСйствия настроСнными ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎ.
  • Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ Tenant, ΠΏΡ€ΠΎΠ²Π΅Ρ€Π΅Π½Π½Ρ‹ΠΉ Lino, вмСсто принятия Ρ€ΡƒΡ‡Π½ΠΎΠΉ смСны, основанной Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π½Π° header, route ΠΈΠ»ΠΈ payload экрана.
  • Π˜Π·Π±Π΅Π³Π°ΠΉΡ‚Π΅ слишком Π±ΠΎΠ»ΡŒΡˆΠΈΡ… claims; Ρ€Π°Π·Π΄ΡƒΡ‚Ρ‹Π΅ tokens ΡƒΡΠ»ΠΎΠΆΠ½ΡΡŽΡ‚ ΡΠΊΡΠΏΠ»ΡƒΠ°Ρ‚Π°Ρ†ΠΈΡŽ ΠΈ ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΠ΅.
  • ЗаписывайтС logs доступа с ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΌ, Tenant ΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠ΅ΠΉ, ΠΊΠΎΠ³Π΄Π° ΠΏΠΎΡ‚ΠΎΠΊ Ρ‚Ρ€Π΅Π±ΡƒΠ΅Ρ‚ Π°ΡƒΠ΄ΠΈΡ‚Π°.

Π’ прилоТСниях с subdomains, Ρ‚Π°ΠΊΠΈΡ… ΠΊΠ°ΠΊ acme.dev.localhost ΠΈ globex.dev.localhost, ITenantContext прСдставляСт Tenant, ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½Ρ‹ΠΉ для запроса. IUserContext прСдставляСт Π°ΡƒΡ‚Π΅Π½Ρ‚ΠΈΡ„ΠΈΡ†ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠ³ΠΎ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ ΠΈ Tenant, ΠΏΡ€ΠΈΡΡƒΡ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΉ Π² JWT. Lino сравниваСт эти Π΄Π²Π° контСкста, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΡ€Π΅Π΄ΠΎΡ‚Π²Ρ€Π°Ρ‚ΠΈΡ‚ΡŒ использованиС token, Π²Ρ‹Π΄Π°Π½Π½ΠΎΠ³ΠΎ для ΠΎΠ΄Π½ΠΎΠ³ΠΎ Tenant, Π² контСкстС Π΄Ρ€ΡƒΠ³ΠΎΠ³ΠΎ Tenant.

Авторизация Ρ‚Π°ΠΊΠΆΠ΅ остаСтся контСкстной. Π Π°Π·Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ ΠΏΡ€ΠΎΡΠΌΠ°Ρ‚Ρ€ΠΈΠ²Π°Ρ‚ΡŒ ΠΏΡ€ΠΎΠ΄ΡƒΠΊΡ‚Ρ‹, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, дСйствуСт Π²Π½ΡƒΡ‚Ρ€ΠΈ Tenant, Π³Π΄Π΅ ΠΎΠ½ΠΎ Π±Ρ‹Π»ΠΎ Π²Ρ‹Π΄Π°Π½ΠΎ ΠΈ для ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒ Π±Ρ‹Π» Π°ΡƒΡ‚Π΅Π½Ρ‚ΠΈΡ„ΠΈΡ†ΠΈΡ€ΠΎΠ²Π°Π½. ΠŸΡ€ΠΈ создании Π½ΠΎΠ²Ρ‹Ρ… Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ ΡƒΠΆΠ΅ доступныС Ρ€Π°Π·Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ ΠΈ контСксты вмСсто создания ΠΎΠ±Ρ…ΠΎΠ΄Π½Ρ‹Ρ… ΠΏΡƒΡ‚Π΅ΠΉ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΏΠΎΠ»ΡƒΡ‡Π°ΡŽΡ‚ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ TenantId ΠΈ ΠΈΠ³Π½ΠΎΡ€ΠΈΡ€ΡƒΡŽΡ‚ Π°ΡƒΡ‚Π΅Π½Ρ‚ΠΈΡ„ΠΈΡ†ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹ΠΉ ΠΏΠΎΡ‚ΠΎΠΊ.

Произошла необработанная ошибка. Обновить πŸ—™