Browse Source

Merge branch 'dev' into auto-merge/prerel-8-2/2714

pull/19812/head
Masum ULU 2 years ago
committed by GitHub
parent
commit
f7f4d6d730
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 2
      Directory.Packages.props
  2. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/en.json
  3. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ar.json
  4. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/cs.json
  5. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/de.json
  6. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json
  7. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/es.json
  8. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fi.json
  9. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fr.json
  10. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hi.json
  11. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hr.json
  12. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hu.json
  13. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/is.json
  14. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/it.json
  15. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/nl.json
  16. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/pl-PL.json
  17. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/pt-BR.json
  18. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ro-RO.json
  19. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sk.json
  20. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sl.json
  21. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/tr.json
  22. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/vi.json
  23. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hans.json
  24. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hant.json
  25. 4
      common.props
  26. BIN
      docs/en/Blog-Posts/2024-05 ABP Unification/abp-studio-solution-runner.png
  27. BIN
      docs/en/Blog-Posts/2024-05 ABP Unification/cover.png
  28. BIN
      docs/en/Blog-Posts/2024-05 ABP Unification/docs-new-navigation.png
  29. BIN
      docs/en/Blog-Posts/2024-05 ABP Unification/docs-project-selection.png
  30. BIN
      docs/en/Blog-Posts/2024-05 ABP Unification/new-get-started.png
  31. BIN
      docs/en/Blog-Posts/2024-05 ABP Unification/new-mega-menu.png
  32. BIN
      docs/en/Blog-Posts/2024-05 ABP Unification/new-pricing.png
  33. 111
      docs/en/Blog-Posts/2024-05 ABP Unification/post.md
  34. BIN
      docs/en/Community-Articles/2024-04-19-using-blob-storage-with-abp/images/blob-storage.png
  35. 114
      docs/en/Community-Articles/2024-04-19-using-blob-storage-with-abp/post.md
  36. 201
      docs/en/Community-Articles/2024-05-01-How-ABP-get-current-user/POST.md
  37. 85
      docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/POST.md
  38. BIN
      docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/access-abp-framework-mvc-project.png
  39. BIN
      docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/add-environment-variables.png
  40. BIN
      docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/azure-container-abp.png
  41. BIN
      docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/azure-resources.png
  42. BIN
      docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/azure-sql-database-connection-strings.png
  43. BIN
      docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/build-docker-image.png
  44. BIN
      docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/check-job-status.png
  45. BIN
      docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/create-azure-container-apps-job.png
  46. BIN
      docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/create-azure-container-apps.png
  47. BIN
      docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/deploy-docker-image.png
  48. BIN
      docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/docker-hub-repository.png
  49. BIN
      docs/en/Community-Articles/2024-05-07-using-fluent-validation-with-abp/images/adding-incorrect-data.png
  50. BIN
      docs/en/Community-Articles/2024-05-07-using-fluent-validation-with-abp/images/error.png
  51. BIN
      docs/en/Community-Articles/2024-05-07-using-fluent-validation-with-abp/images/validation.png
  52. 115
      docs/en/Community-Articles/2024-05-07-using-fluent-validation-with-abp/post.md
  53. 336
      docs/en/Community-Articles/2024-05-10-Sentiment-Analysis-within-ABP-Based-Application/POST.md
  54. BIN
      docs/en/Community-Articles/2024-05-10-Sentiment-Analysis-within-ABP-Based-Application/cover-image.png
  55. BIN
      docs/en/Community-Articles/2024-05-10-Sentiment-Analysis-within-ABP-Based-Application/demo.gif
  56. BIN
      docs/en/Community-Articles/2024-05-10-Sentiment-Analysis-within-ABP-Based-Application/sentiment-analysis-steps.png
  57. BIN
      docs/en/Community-Articles/2024-05-10-Sentiment-Analysis-within-ABP-Based-Application/sentiment-analysis.png
  58. 3
      docs/pt-BR/AspNetCore/Auto-API-Controllers.md
  59. 3
      docs/pt-BR/AspNetCore/Bundling-Minification.md
  60. 3
      docs/pt-BR/AspNetCore/Client-Side-Package-Management.md
  61. 3
      docs/pt-BR/AspNetCore/Dynamic-CSharp-API-Clients.md
  62. 3
      docs/pt-BR/AspNetCore/Tag-Helpers/Dynamic-Forms.md
  63. 3
      docs/pt-BR/AspNetCore/Tag-Helpers/Index.md
  64. 3
      docs/pt-BR/AspNetCore/Theming.md
  65. 3
      docs/pt-BR/AspNetCore/Widgets.md
  66. 391
      docs/pt-BR/Audit-Logging.md
  67. 360
      docs/pt-BR/Authorization.md
  68. 159
      docs/pt-BR/Background-Jobs-Quartz.md
  69. 146
      docs/pt-BR/Background-Workers-Quartz.md
  70. 144
      docs/pt-BR/Background-Workers.md
  71. 343
      docs/pt-BR/Exception-Handling.md
  72. 80
      docs/pt-BR/Modules/Account.md
  73. 60
      docs/pt-BR/Modules/Audit-Logging.md
  74. 55
      docs/pt-BR/Modules/Background-Jobs.md
  75. 135
      docs/pt-BR/Modules/Cms-Kit/Blogging.md
  76. 144
      docs/pt-BR/Modules/Cms-Kit/Comments.md
  77. 137
      docs/pt-BR/Modules/Cms-Kit/Dynamic-Widget.md
  78. 72
      docs/pt-BR/Modules/Cms-Kit/Global-Resources.md
  79. 143
      docs/pt-BR/Modules/Cms-Kit/Index.md
  80. 90
      docs/pt-BR/Modules/Cms-Kit/Menus.md
  81. 33
      docs/pt-BR/Modules/Cms-Kit/Pages.md
  82. 111
      docs/pt-BR/Modules/Cms-Kit/Ratings.md
  83. 126
      docs/pt-BR/Modules/Cms-Kit/Reactions.md
  84. 165
      docs/pt-BR/Modules/Cms-Kit/Tags.md
  85. 577
      docs/pt-BR/Modules/Database-Tables.md
  86. 675
      docs/pt-BR/Modules/Docs.md
  87. 105
      docs/pt-BR/Modules/Feature-Management.md
  88. 321
      docs/pt-BR/Modules/Identity.md
  89. 175
      docs/pt-BR/Modules/IdentityServer.md
  90. 32
      docs/pt-BR/Modules/Index.md
  91. 514
      docs/pt-BR/Modules/OpenIddict.md
  92. 109
      docs/pt-BR/Modules/Permission-Management.md
  93. 313
      docs/pt-BR/Modules/Setting-Management.md
  94. 134
      docs/pt-BR/Modules/Tenant-Management.md
  95. 87
      docs/pt-BR/Modules/Virtual-File-Explorer.md
  96. 74
      docs/pt-BR/UI/AspNetCore/AutoComplete-Select.md
  97. 96
      docs/pt-BR/UI/AspNetCore/Basic-Theme.md
  98. 45
      docs/pt-BR/UI/AspNetCore/Branding.md
  99. 479
      docs/pt-BR/UI/AspNetCore/Bundling-Minification.md
  100. 115
      docs/pt-BR/UI/AspNetCore/Client-Side-Package-Management.md

2
Directory.Packages.props

@ -174,4 +174,4 @@
<PackageVersion Include="ConfigureAwait.Fody" Version="3.3.2" />
<PackageVersion Include="Fody" Version="6.8.0" />
</ItemGroup>
</Project>
</Project>

3
abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/en.json

@ -12,6 +12,7 @@
"CommunityWebSite": "ABP community website",
"ManageAccount": "My Account | ABP.IO",
"ManageYourProfile": "Manage your profile",
"ReturnToApplication": "Return to application"
"ReturnToApplication": "Return to application",
"IdentityUserNotAvailable:Deleted": "This email address is not available. Reason: Already deleted."
}
}

4
abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ar.json

@ -259,6 +259,8 @@
"MarkdownSupported": "<a href=\"https://www.markdownguide.org/basic-syntax/\">Markdown</a> أيد.",
"Preview": "معاينة",
"VisitVideoCourseDescription": "إذا كنت ترغب في تعلم أساسيات إطار عمل برنامج ABP، فاطلع على دورات الفيديو الخاصة ببرنامج ABP Essentials.",
"VisitPage": "زر الصفحة"
"VisitPage": "زر الصفحة",
"ConfirmEmailForPost": "لتتمكن من النشر، تحتاج إلى تأكيد بريدك الإلكتروني. انتقل إلى account.abp.io/Account/Manage وتحقق من بريدك الإلكتروني في علامة التبويب \"المعلومات الشخصية\".",
"DailyPostCreateLimitation": "لقد وصلت إلى الحد الأقصى اليومي لإنشاء المنشورات. يمكنك إنشاء مشاركة جديدة في {0}."
}
}

4
abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/cs.json

@ -259,6 +259,8 @@
"MarkdownSupported": "<a href=\"https://www.markdownguide.org/basic-syntax/\">Markdown</a> podporováno.",
"Preview": "Náhled",
"VisitPage": "Navštivte stránku",
"VisitVideoCourseDescription": "Pokud se chcete naučit základy rámce ABP, podívejte se na videokurzy ABP Essentials."
"VisitVideoCourseDescription": "Pokud se chcete naučit základy rámce ABP, podívejte se na videokurzy ABP Essentials.",
"ConfirmEmailForPost": "Abyste mohli přidávat příspěvky, musíte potvrdit svůj e-mail. Přejděte na stránku account.abp.io/Account/Manage a ověřte svůj e-mail na kartě Osobní údaje.",
"DailyPostCreateLimitation": "Dosáhli jste denního limitu pro vytváření příspěvků. Nový příspěvek můžete vytvořit v {0}."
}
}

4
abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/de.json

@ -259,6 +259,8 @@
"MarkdownSupported": "<a href=\"https://www.markdownguide.org/basic-syntax/\">Markdown</a> unterstützt.",
"Preview": "Vorschau",
"VisitPage": "Seite besuchen",
"VisitVideoCourseDescription": "Wenn Sie die Grundlagen des ABP Framework erlernen möchten, schauen Sie sich die ABP Essentials-Videokurse an."
"VisitVideoCourseDescription": "Wenn Sie die Grundlagen des ABP Framework erlernen möchten, schauen Sie sich die ABP Essentials-Videokurse an.",
"ConfirmEmailForPost": "Um Beiträge verfassen zu können, müssen Sie Ihre E-Mail-Adresse bestätigen. Gehen Sie zu account.abp.io/Account/Manage und bestätigen Sie Ihre E-Mail-Adresse auf der Registerkarte „Persönliche Daten“.",
"DailyPostCreateLimitation": "Sie haben das tägliche Limit für die Erstellung von Beiträgen erreicht. Sie können in {0} einen neuen Beitrag erstellen."
}
}

4
abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json

@ -261,6 +261,8 @@
"Preview": "Preview",
"VisitPage": "Visit Page",
"VisitVideoCourseDescription": "If you want to learn the basics of the ABP Framework, check out the ABP Essentials Video courses.",
"EditProfile": "Edit Profile"
"EditProfile": "Edit Profile",
"ConfirmEmailForPost": "To be able to post, you need to confirm your email. Go to account.abp.io/Account/Manage and verify your email in the Personal Info tab.",
"DailyPostCreateLimitation": "You have reached the daily post creation limit. You can create a new post in {0}."
}
}

4
abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/es.json

@ -259,6 +259,8 @@
"MarkdownSupported": "<a href=\"https://www.markdownguide.org/basic-syntax/\">Markdown</a> soportado.",
"Preview": "Avance",
"VisitPage": "Visita la página",
"VisitVideoCourseDescription": "Si desea aprender los conceptos básicos del marco ABP, consulte los cursos en vídeo de ABP Essentials."
"VisitVideoCourseDescription": "Si desea aprender los conceptos básicos del marco ABP, consulte los cursos en vídeo de ABP Essentials.",
"ConfirmEmailForPost": "Para poder publicar, debe confirmar su correo electrónico. Vaya a account.abp.io/Account/Manage y verifique su correo electrónico en la pestaña Información personal.",
"DailyPostCreateLimitation": "Has alcanzado el límite diario de creación de publicaciones. Puedes crear una nueva publicación en {0}."
}
}

4
abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fi.json

@ -259,6 +259,8 @@
"MarkdownSupported": "<a href=\"https://www.markdownguide.org/basic-syntax/\">Markdown</a> tuettu.",
"Preview": "Esikatselu",
"VisitPage": "Vieraile sivulla",
"VisitVideoCourseDescription": "Jos haluat oppia ABP Frameworkin perusteet, katso ABP Essentials Video -kurssit."
"VisitVideoCourseDescription": "Jos haluat oppia ABP Frameworkin perusteet, katso ABP Essentials Video -kurssit.",
"ConfirmEmailForPost": "Jotta voit lähettää viestejä, sinun on vahvistettava sähköpostiosoitteesi. Siirry osoitteeseen account.abp.io/Account/Manage ja vahvista sähköpostiosoitteesi Henkilökohtaiset tiedot -välilehdessä.",
"DailyPostCreateLimitation": "Olet saavuttanut päivittäisen viestien luomisrajan. Voit luoda uuden viestin kohteessa {0}."
}
}

4
abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fr.json

@ -259,6 +259,8 @@
"MarkdownSupported": "<a href=\"https://www.markdownguide.org/basic-syntax/\">Markdown</a> prise en charge.",
"Preview": "Aperçu",
"VisitPage": "Page de visite",
"VisitVideoCourseDescription": "Si vous souhaitez apprendre les bases du framework ABP, consultez les cours vidéo ABP Essentials."
"VisitVideoCourseDescription": "Si vous souhaitez apprendre les bases du framework ABP, consultez les cours vidéo ABP Essentials.",
"ConfirmEmailForPost": "Pour pouvoir publier, vous devez confirmer votre e-mail. Accédez à account.abp.io/Account/Manage et vérifiez votre e-mail dans l'onglet Informations personnelles.",
"DailyPostCreateLimitation": "Vous avez atteint la limite quotidienne de création de publications. Vous pouvez créer une nouvelle publication dans {0}."
}
}

4
abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hi.json

@ -259,6 +259,8 @@
"MarkdownSupported": "<a href=\"https://www.markdownguide.org/basic-syntax/\">Markdown</a> का समर्थन किया।",
"Preview": "पूर्व दर्शन",
"VisitPage": "यात्रा पेज",
"VisitVideoCourseDescription": "यदि आप एबीपी फ्रेमवर्क की मूल बातें सीखना चाहते हैं, तो एबीपी एसेंशियल वीडियो पाठ्यक्रम देखें।"
"VisitVideoCourseDescription": "यदि आप एबीपी फ्रेमवर्क की मूल बातें सीखना चाहते हैं, तो एबीपी एसेंशियल वीडियो पाठ्यक्रम देखें।",
"ConfirmEmailForPost": "पोस्ट करने में सक्षम होने के लिए, आपको अपने ईमेल की पुष्टि करनी होगी। account.abp.io/Account/Manage पर जाएं और व्यक्तिगत जानकारी टैब में अपना ईमेल सत्यापित करें।",
"DailyPostCreateLimitation": "आप दैनिक पोस्ट निर्माण सीमा तक पहुंच गए हैं। आप {0} में एक नई पोस्ट बना सकते हैं।"
}
}

4
abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hr.json

@ -259,6 +259,8 @@
"MarkdownSupported": "<a href=\"https://www.markdownguide.org/basic-syntax/\">Markdown</a> podržan.",
"Preview": "Pregled",
"VisitPage": "Posjetite stranicu",
"VisitVideoCourseDescription": "Ako želite naučiti osnove ABP okvira, pogledajte video tečajeve ABP Essentials."
"VisitVideoCourseDescription": "Ako želite naučiti osnove ABP okvira, pogledajte video tečajeve ABP Essentials.",
"ConfirmEmailForPost": "Da biste mogli objavljivati, morate potvrditi svoju e-poštu. Idite na account.abp.io/Account/Manage i potvrdite svoju e-poštu na kartici Osobni podaci.",
"DailyPostCreateLimitation": "Dosegli ste dnevno ograničenje za izradu postova. Možete stvoriti novi post u {0}."
}
}

4
abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hu.json

@ -259,6 +259,8 @@
"MarkdownSupported": "<a href=\"https://www.markdownguide.org/basic-syntax/\">Markdown</a> támogatott.",
"Preview": "Előnézet",
"VisitPage": "Látogassa meg az oldalt",
"VisitVideoCourseDescription": "Ha meg szeretné tanulni az ABP Framework alapjait, nézze meg az ABP Essentials Video tanfolyamokat."
"VisitVideoCourseDescription": "Ha meg szeretné tanulni az ABP Framework alapjait, nézze meg az ABP Essentials Video tanfolyamokat.",
"ConfirmEmailForPost": "A bejegyzések közzétételéhez meg kell erősítenie e-mail-címét. Nyissa meg az account.abp.io/Account/Manage oldalt, és ellenőrizze e-mail-címét a Személyes adatok lapon.",
"DailyPostCreateLimitation": "Elérte a napi bejegyzéslétrehozási korlátot. Új bejegyzést itt hozhat létre: {0}."
}
}

4
abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/is.json

@ -259,6 +259,8 @@
"MarkdownSupported": "<a href=\"https://www.markdownguide.org/basic-syntax/\">Markdown</a> stutt.",
"Preview": "Forskoðun",
"VisitPage": "Heimsæktu síðu",
"VisitVideoCourseDescription": "Ef þú vilt læra grunnatriði ABP Framework skaltu skoða ABP Essentials Video námskeiðin."
"VisitVideoCourseDescription": "Ef þú vilt læra grunnatriði ABP Framework skaltu skoða ABP Essentials Video námskeiðin.",
"ConfirmEmailForPost": "Til að geta sent færslur þarftu að staðfesta netfangið þitt. Farðu á account.abp.io/Account/Manage og staðfestu tölvupóstinn þinn á Persónulegum upplýsingum flipanum.",
"DailyPostCreateLimitation": "Þú hefur náð daglegu takmörkunum fyrir færslu færslu. Þú getur búið til nýja færslu í {0}."
}
}

4
abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/it.json

@ -259,6 +259,8 @@
"MarkdownSupported": "<a href=\"https://www.markdownguide.org/basic-syntax/\">Markdown</a> supportato.",
"Preview": "Anteprima",
"VisitPage": "Visita la pagina",
"VisitVideoCourseDescription": "Se vuoi apprendere le nozioni di base del Framework ABP, dai un'occhiata ai corsi video ABP Essentials."
"VisitVideoCourseDescription": "Se vuoi apprendere le nozioni di base del Framework ABP, dai un'occhiata ai corsi video ABP Essentials.",
"ConfirmEmailForPost": "Per poter pubblicare, devi confermare la tua email. Vai su account.abp.io/Account/Manage e verifica la tua email nella scheda Informazioni personali.",
"DailyPostCreateLimitation": "Hai raggiunto il limite giornaliero di creazione di post. Puoi creare un nuovo post in {0}."
}
}

4
abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/nl.json

@ -259,6 +259,8 @@
"MarkdownSupported": "<a href=\"https://www.markdownguide.org/basic-syntax/\">Markdown</a> ondersteund.",
"Preview": "Voorbeeld",
"VisitPage": "Bezoek pagina",
"VisitVideoCourseDescription": "Als je de basis van het ABP Framework wilt leren, bekijk dan de ABP Essentials Videocursussen."
"VisitVideoCourseDescription": "Als je de basis van het ABP Framework wilt leren, bekijk dan de ABP Essentials Videocursussen.",
"ConfirmEmailForPost": "Om te kunnen posten, moet u uw e-mailadres bevestigen. Ga naar account.abp.io/Account/Manage en verifieer uw e-mailadres op het tabblad Persoonlijke informatie.",
"DailyPostCreateLimitation": "Je hebt de dagelijkse limiet voor het maken van berichten bereikt. Je kunt een nieuw bericht maken in {0}."
}
}

4
abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/pl-PL.json

@ -259,6 +259,8 @@
"MarkdownSupported": "<a href=\"https://www.markdownguide.org/basic-syntax/\">Markdown</a> utrzymany.",
"Preview": "Zapowiedź",
"VisitPage": "Odwiedź stronę",
"VisitVideoCourseDescription": "Jeśli chcesz poznać podstawy ABP Framework, sprawdź kursy wideo ABP Essentials."
"VisitVideoCourseDescription": "Jeśli chcesz poznać podstawy ABP Framework, sprawdź kursy wideo ABP Essentials.",
"ConfirmEmailForPost": "Aby móc publikować, musisz potwierdzić swój adres e-mail. Przejdź do account.abp.io/Account/Manage i zweryfikuj swój adres e-mail w zakładce Dane osobowe.",
"DailyPostCreateLimitation": "Osiągnąłeś dzienny limit tworzenia postów. Możesz utworzyć nowy post w {0}."
}
}

4
abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/pt-BR.json

@ -259,6 +259,8 @@
"MarkdownSupported": "<a href=\"https://www.markdownguide.org/basic-syntax/\">Markdown</a> suportado.",
"Preview": "Visualização",
"VisitPage": "Visite a página",
"VisitVideoCourseDescription": "Se você quiser aprender o básico do ABP Framework, confira os cursos em vídeo ABP Essentials."
"VisitVideoCourseDescription": "Se você quiser aprender o básico do ABP Framework, confira os cursos em vídeo ABP Essentials.",
"ConfirmEmailForPost": "Para poder postar, você precisa confirmar seu e-mail. Acesse account.abp.io/Account/Manage e verifique seu e-mail na guia Informações pessoais.",
"DailyPostCreateLimitation": "Você atingiu o limite diário de criação de postagens. Você pode criar uma nova postagem em {0}."
}
}

4
abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ro-RO.json

@ -259,6 +259,8 @@
"MarkdownSupported": "<a href=\"https://www.markdownguide.org/basic-syntax/\">Markdown</a> sprijinit.",
"Preview": "previzualizare",
"VisitPage": "Vizitați pagina",
"VisitVideoCourseDescription": "Dacă doriți să aflați elementele de bază ale cadrului ABP, consultați cursurile video ABP Essentials."
"VisitVideoCourseDescription": "Dacă doriți să aflați elementele de bază ale cadrului ABP, consultați cursurile video ABP Essentials.",
"ConfirmEmailForPost": "Pentru a putea posta, trebuie să vă confirmați adresa de e-mail. Accesați account.abp.io/Account/Manage și verificați e-mailul în fila Informații personale.",
"DailyPostCreateLimitation": "Ați atins limita zilnică de creare a postărilor. Puteți crea o postare nouă în {0}."
}
}

4
abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sk.json

@ -259,6 +259,8 @@
"MarkdownSupported": "<a href=\"https://www.markdownguide.org/basic-syntax/\">Markdown</a> podporované.",
"Preview": "Náhľad",
"VisitPage": "Navštívte stránku",
"VisitVideoCourseDescription": "Ak sa chcete naučiť základy rámca ABP, pozrite si video kurzy ABP Essentials."
"VisitVideoCourseDescription": "Ak sa chcete naučiť základy rámca ABP, pozrite si video kurzy ABP Essentials.",
"ConfirmEmailForPost": "Aby ste mohli uverejňovať príspevky, musíte potvrdiť svoj e-mail. Prejdite na stránku account.abp.io/Account/Manage a overte svoj e-mail na karte Osobné informácie.",
"DailyPostCreateLimitation": "Dosiahli ste denný limit na vytváranie príspevkov. Nový príspevok môžete vytvoriť v {0}."
}
}

4
abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sl.json

@ -259,6 +259,8 @@
"MarkdownSupported": "<a href=\"https://www.markdownguide.org/basic-syntax/\">Markdown</a> podprt.",
"Preview": "Predogled",
"VisitPage": "Obiščite stran",
"VisitVideoCourseDescription": "Če se želite naučiti osnov ogrodja ABP, si oglejte video tečaje ABP Essentials."
"VisitVideoCourseDescription": "Če se želite naučiti osnov ogrodja ABP, si oglejte video tečaje ABP Essentials.",
"ConfirmEmailForPost": "Če želite objavljati, morate potrditi svoj e-poštni naslov. Pojdite na account.abp.io/Account/Manage in potrdite svoj e-poštni naslov na zavihku Osebni podatki.",
"DailyPostCreateLimitation": "Dosegli ste dnevno omejitev za ustvarjanje objav. Novo objavo lahko ustvarite v {0}."
}
}

4
abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/tr.json

@ -244,6 +244,8 @@
"BuyTicket": "Bilet al",
"SeeEvent": "Etkinliği Gör",
"Cancel": "Vazgeç",
"Continue": "Devam"
"Continue": "Devam",
"ConfirmEmailForPost": "Gönderi paylaşabilmek için e-posta adresinizi onaylamanız gerekir. account.abp.io/Account/Manage adresine gidin ve Kişisel Bilgiler sekmesinden e-posta adresinizi doğrulayın.",
"DailyPostCreateLimitation": "Günlük gönderi paylaşma sınırına ulaştınız. {0}'da yeni bir gönderi paylaşabilirsiniz."
}
}

4
abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/vi.json

@ -259,6 +259,8 @@
"MarkdownSupported": "<a href=\"https://www.markdownguide.org/basic-syntax/\">Markdown</a> được hỗ trợ.",
"Preview": "Xem trước",
"VisitPage": "Ghé thăm trang",
"VisitVideoCourseDescription": "Nếu bạn muốn tìm hiểu những kiến ​​thức cơ bản về Khung ABP, hãy xem các khóa học Video Cơ bản về ABP."
"VisitVideoCourseDescription": "Nếu bạn muốn tìm hiểu những kiến ​​thức cơ bản về Khung ABP, hãy xem các khóa học Video Cơ bản về ABP.",
"ConfirmEmailForPost": "Để có thể đăng bài, bạn cần xác nhận email của mình. Hãy truy cập account.abp.io/Account/Quản lý và xác minh email của bạn trong tab Thông tin cá nhân.",
"DailyPostCreateLimitation": "Bạn đã đạt đến giới hạn tạo bài đăng hàng ngày. Bạn có thể tạo bài đăng mới trong {0}."
}
}

4
abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hans.json

@ -259,6 +259,8 @@
"MarkdownSupported": "<a href=\"https://www.markdownguide.org/basic-syntax/\">Markdown</a> 支持的。",
"Preview": "预览",
"VisitPage": "访问页面",
"VisitVideoCourseDescription": "如果您想学习 ABP 框架的基础知识,请查看 ABP Essentials 视频课程。"
"VisitVideoCourseDescription": "如果您想学习 ABP 框架的基础知识,请查看 ABP Essentials 视频课程。",
"ConfirmEmailForPost": "为了能够发帖,您需要确认您的电子邮件。转到 account.abp.io/Account/Manage 并在“个人信息”选项卡中验证您的电子邮件。",
"DailyPostCreateLimitation": "您已达到每日帖子创建限制。您可以在 {0} 中创建新帖子。"
}
}

4
abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hant.json

@ -259,6 +259,8 @@
"MarkdownSupported": "<a href=\"https://www.markdownguide.org/basic-syntax/\">Markdown</a> 支持的。",
"Preview": "预览",
"VisitPage": "访问页面",
"VisitVideoCourseDescription": "如果您想学习 ABP 框架的基础知识,请查看 ABP Essentials 视频课程。"
"VisitVideoCourseDescription": "如果您想学习 ABP 框架的基础知识,请查看 ABP Essentials 视频课程。",
"ConfirmEmailForPost": "为了能够发帖,您需要确认您的电子邮件。转到 account.abp.io/Account/Manage 并在“个人信息”选项卡中验证您的电子邮件。",
"DailyPostCreateLimitation": "您已达到每日帖子创建限制。您可以在 {0} 中创建新帖子。"
}
}

4
common.props

@ -1,8 +1,8 @@
<Project>
<PropertyGroup>
<LangVersion>latest</LangVersion>
<Version>8.2.0-preview</Version>
<LeptonXVersion>3.2.0-preview</LeptonXVersion>
<Version>8.3.0-preview</Version>
<LeptonXVersion>3.3.0-preview</LeptonXVersion>
<NoWarn>$(NoWarn);CS1591;CS0436</NoWarn>
<PackageIconUrl>https://abp.io/assets/abp_nupkg.png</PackageIconUrl>
<PackageProjectUrl>https://abp.io/</PackageProjectUrl>

BIN
docs/en/Blog-Posts/2024-05 ABP Unification/abp-studio-solution-runner.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

BIN
docs/en/Blog-Posts/2024-05 ABP Unification/cover.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

BIN
docs/en/Blog-Posts/2024-05 ABP Unification/docs-new-navigation.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

BIN
docs/en/Blog-Posts/2024-05 ABP Unification/docs-project-selection.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
docs/en/Blog-Posts/2024-05 ABP Unification/new-get-started.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 391 KiB

BIN
docs/en/Blog-Posts/2024-05 ABP Unification/new-mega-menu.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 262 KiB

BIN
docs/en/Blog-Posts/2024-05 ABP Unification/new-pricing.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 KiB

111
docs/en/Blog-Posts/2024-05 ABP Unification/post.md

@ -0,0 +1,111 @@
# Unifying the ABP.IO Platform
I am very excited to announce that some big changes and improvements are coming to the ABP.IO Platform soon. In this post, I will explain the changes we are currently working on. Here, a brief list of these changes:
* We are merging the subdomains of the ABP.IO Platform websites: Community.abp.io, commercial.abp.io, blog.abp.io, docs.abp.io websites and their contents are being merged into the main domain, abp.io.
* ABP (open source) and ABP Commercial documents are being merged into a single documentation.
* Introducing ABP Studio Community Edition.
These changes won't effect the license conditions. The open source part will remain the same and the commercial license contents will also be the same. The aim of the changes is to make the platform more consistent, holistic, understandable and easy to start.
Let's dive deep...
## Merging the ABP.IO Websites
ABP.IO website has many subdomains currently:
* **abp.io**: Home page of the open source ABP Framework project.
* **community.abp.io**: A website that community can share contents and we organize events.
* **commercial.abp.io**: A website to promote and sell commercial ABP licenses which have pre-built modules, themes, tooling and support on top of the ABP Framework.
* **docs.abp.io**: The technical documentation of the ABP Framework and ABP Commercial.
* **blog.abp.io**: A blog website to announce the news on the platform.
* **support.abp.io**: Premium support for the ABP Commercial customers.
All these subdomains (except the support website for now) are being merged to the abp.io domain. All their contents and UI designs are being revised and enriched.
Some fundamental purposes of that change are;
* Making content more coherent and holistic,
* Making the design more harmonious,
* Making the contents of the old subdomains more visible and reachable,
* Allow you to navigate through the web pages much easier,
* Reducing duplications between different websites,
I will highlight a few important changes in the next sections.
### The New Mega Menu
As I said above, the abp.io UI design is also being revised. One of the big revisions is the main menu. We are replacing the current main navigation by a mega menu as shown in the following figure:
![new-mega-menu](new-mega-menu.png)
We believe that new mega menu will allow you to navigate through the web pages much easier.
### The New Get Started Page
We are constantly working to improve ABP's onboarding experience. With the new platform changes, we now offer ABP Studio as the starting point for the ABP Platform. You can still use the [ABP CLI](https://docs.abp.io/en/abp/latest/CLI) to created new ABP solutions, but the new ABP Studio makes it much easier and understandable. It also provides features to easily run and monitor your applications, even in the Community edition.
![new-get-started](new-get-started.png)
You can easily download and install ABP Studio, login with your abp.io account and create your first ABP solution.
### The New Pricing Page
Since the [ABP Commercial website](https://commercial.abp.io/) has merged with the main website, you will see the *Pricing* page located on the main menu of the abp.io website. We have completely revised the design and content of this page to better reflect which features are open source and free, and what is included in the paid licenses.
![new-pricing](new-pricing.png)
As mentioned above, all the free & open source features are still free & open source. In addition, we included the ABP Studio Community edition (will be explained below) to the free license.
## Merging the ABP Platform Documentation
Currently, ABP Framework (open source) and ABP Commercial [documents](https://docs.abp.io/) are completely separated. You can switch between them on the left side:
![docs-project-selection](docs-project-selection.png)
Based on our and customers' experiences, there are some problems with that approach:
* Getting started, development tutorials, release notes, road map and some other documents are duplicated (or very similar) among ABP Framework and ABP Commercial documents.
* For ABP Commercial users, it is not clear if they also need to read the ABP Framework (open source) documentation or not. Also, when they read the framework document, some parts are different for ABP Commercial users, and it is also not clear in some cases.
We are currently working to completely merge the ABP Framework (open source) and ABP Commercial documentation, remove duplications and revisit the contents. We will clearly indicate if a part of a document requires a paid license.
The left navigation panel tree is also completely revisited and simplified:
![docs-new-navigation](docs-new-navigation.png)
## The ABP Studio Community Edition
[ABP Studio](https://docs.abp.io/en/commercial/latest/studio/index) is a cross-platform desktop application designed for ABP and .NET developers. It aims to provide a comfortable development environment by automating tasks, providing insights about your solution, and simplifying the processes of creation, development, execution, browsing, monitoring, tracing, and deploying your solutions.
Here, a screenshot from the *Solution Runner* screen of ABP Studio:
![abp-studio-solution-runner](abp-studio-solution-runner.png)
ABP Studio has been started as a commercial product, as a part of [ABP Commercial](https://commercial.abp.io/). We are very excited to announce that the *Community Edition* will be available soon for free. It will have some missing features and limitations compared to the full edition, but will be enough to create, explore and run ABP solutions easily.
We will be offering ABP Studio as a starting point to the ABP platform. The [Getting Started](https://docs.abp.io/en/abp/latest/Getting-Started-Overall) and other documents will use ABP Studio to create new solutions and perform ABP-related operations.
## Other News
We are also working on some other topics related to these changes. Some of them are;
* Completely renewing the [startup templates](https://docs.abp.io/en/abp/latest/Startup-Templates/Index) (with ABP Studio), so they will be more flexible and will provide more options.
* Providing a tool to automatically convert ABP solutions created with open source startup templates into ABP commercial.
## Questions
I tried to explain all the important changes in this post. However, you may have some questions in your mind.
### What should open source users expect?
Since the [ABP Commercial](https://commercial.abp.io/) website content is merged with the main [abp.io](https://abp.io/) website, you will see paid features being introduced on the main website. The pricing page will also be available on the same website. This may lead you to wonder whether the ABP Platform is a fully paid product. The simple answer to this question is "No". Actually, nothing has changed on the open source side. Everything will be the same. Additionally, open source users will now have ABP Studio Community Edition for free. So open source has more for its users than before.
### What should ABP Commercial customers expect?
ABP Commercial license holders may wonder if any license change happens. The answer is "No". All the license types, rules, restrictions and features are the same. With the changes explained in this post, you will follow the documentation easier (since you won't need to go to another website for the framework documentation) and you will better understand what special features are available to you.
## Last Words
With this post, we wanted to announce the changes to be made on the ABP platform to the ABP community, so don't be surprised or curious about what happened. If you have any questions or suggestions, feel free to write a comment for this blog post or send an email to info@abp.io.

BIN
docs/en/Community-Articles/2024-04-19-using-blob-storage-with-abp/images/blob-storage.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

114
docs/en/Community-Articles/2024-04-19-using-blob-storage-with-abp/post.md

@ -0,0 +1,114 @@
# Using Blob Storage with ABP
ABP Framework provides a comprehensive solution to meet the needs of modern application development, while addressing the important requirement of BLOB Storing. ABP Framework [provides an easy integration for Blob Storing](https://docs.abp.io/en/abp/latest/Blob-Storing) and offers many storage services that you can easily integrate. In addition to efficiently storing large files, these services offer significant advantages such as scalability, security and backup.
## What is Blob Storage ?
Blob Storage is a service for storing unstructured data. It is becoming increasingly important to efficiently store and manage large data types (e.g. images, videos, documents). Blob Storage was developed to meet these needs and offers a secure solution with the advantages of scalability, durability and low cost.
![Blob Stroge](./images/blob-storage.png)
## How to use Blob Storage ?
I would like to explain this to you with an example.For example, storing large files such as user profile pictures in the database negatively affects the performance and database.You can store this data using Blob storage. One of the advantages of storing user profile pictures in blob storage is that it improves database performance. Blob storage is a more efficient option than storing large size files in the database and allows database queries to run faster. Furthermore, blob storage provides scalability, so that the number of profile pictures can grow with the number of users, but without storage issues. This approach also maintains database normalization and makes the database design cleaner.
How do we store user profile pictures with Blob Storage using ABP Framework?
- #### Step 1: Configure the Blob Container
Define a Blob Container named `profile-pictures` using the `[BlobContainerName("profile-pictures")]` attribute.
````csharp
[BlobContainerName("profile-pictures")]
public class ProfilePictureContainer
{
}
````
- #### Step 2: Create the ProfileAppService (Saving & Reading BLOBs)
Create the `ProfileAppService` class and derive it from the `ApplicationService` class. This class will perform the necessary operations to store and retrieve profile pictures.
````csharp
using Volo.Abp.Application.Services;
public class ProfileAppService : ApplicationService
{
// Code snippets will come here
}
````
- #### Step 3: Inject the `IBlobContainer` Service
Inject the `IBlobContainer` service, in the constructor of the `ProfileAppService` class. The `IBlobContainer` is the main interface to store and read BLOB and is used to interact with the container.
````csharp
private readonly IBlobContainer<ProfilePictureContainer> _blobContainer;
public ProfileAppService(IBlobContainer<ProfilePictureContainer> blobContainer)
{
_blobContainer = blobContainer;
}
````
- #### Step 4: Save Profile Picture
The SaveProfilePictureAsync method is used to store the user's profile picture. A unique name is generated based on the user's credentials and the profile picture byte array with this name is saved in the Blob Container.
````csharp
public async Task SaveProfilePictureAsync(byte[] bytes)
{
var blobName = CurrentUser.GetId().ToString();
await _blobContainer.SaveAsync(blobName, bytes);
}
````
- #### Step 5: Getting Profile Picture
The GetProfilePictureAsync method is used to get the user's profile picture. A profile picture byte array is retrieved from the Blob Container with a specified name based on the user's credential.
````csharp
public async Task<byte[]> GetProfilePictureAsync()
{
var blobName = CurrentUser.GetId().ToString();
return await _blobContainer.GetAllBytesOrNullAsync(blobName);
}
````
Finally, add controls in the user interface that will allow users to upload and view their profile pictures. These controls will perform the operations by calling the corresponding methods in the ProfileAppService class.
These steps cover the basic steps to store user profile pictures with Blob Storage using the ABP Framework. [Check out the documentation for more information.](https://docs.abp.io/en/abp/latest/Blob-Storing)
## What are the Advantages/Disadvantages of Keeping the BLOBs in a Database?
#### Advantages:
- Data Integrity and Relational Model: To ensure data integrity and preserve the relational model, it is important to store blob data in the database. This approach preserves the relationships between data and maintains the structural integrity of the database.
- A Single Storage Location: Storing blob data in the database allows you to collect all data in a single storage location. This simplifies the management of data and increases data integrity.
- Advanced Security Controls: Database systems often offer advanced security controls. Storing blob data in a database allows you to take advantage of these security features and ensures that data is accessed by authorized users.
#### Disadvantages:
- Performance Issues: Storing blob data in a database can negatively impact database performance. Oversized blob data can slow down query processing and reduce database performance.
- Storage Space Issue: Storing blob data in the database can increase the size of the database and require more storage space. This can increase storage costs and complicate infrastructure requirements.
- Backup and Recovery Challenges: Storing blob data in a database can make backup and recovery difficult. The large size of blob data can make backup and recovery time-consuming and data recovery difficult.
## Other Blob Storage Providers
ABP Framework provides developers with a variety of options and flexibility by offering integration infrastructure for multiple cloud providers. This makes it easy for users to choose between different cloud platforms and select the most suitable solution for their business needs.
- Azure Blob Storage: A cloud storage service offered on the Microsoft Azure platform. It is used to store and access large amounts of data. It supports various data types such as files, images, videos and provides high scalability. ABP Framework provides integration with [Azure Blob Storage](https://docs.abp.io/en/abp/latest/Blob-Storing-Azure).
- Aliyun Object Storage Service (OSS): OSS, Alibaba Cloud's cloud storage service, is an ideal solution for use cases such as big data storage, backup and media storage. It offers flexible storage options and provides a high level of security. ABP Framework interfaces with [Aliyun Blob Storage](https://docs.abp.io/en/abp/latest/Blob-Storing-Aliyun), making it easier for developers to manage data storage and access.
- MinIO: MinIO is known as an open source object storage system and offers an Amazon S3 compatible cloud storage solution. It is a high-performance, scalable and fast storage service. ABP Framework integrates with [MinIO Blob Storage](https://docs.abp.io/en/abp/latest/Blob-Storing-Minio) to provide developers with cloud-based file and object storage.
- Amazon Simple Storage Service (S3): Amazon S3 is a cloud storage service offered on the Amazon Web Services (AWS) platform. It can be used to store virtually unlimited amounts of data. It provides high durability, scalability and low cost.ABP Framework integrates with [Amazon S3 Blob Storage](https://docs.abp.io/en/abp/latest/Blob-Storing-Aws) to provide developers with cloud-based file and object storage.

201
docs/en/Community-Articles/2024-05-01-How-ABP-get-current-user/POST.md

@ -0,0 +1,201 @@
# How claim type works in ASP NET Core and ABP Framework
## The Claim Type
A web application may use one or more authentication schemes to obtain the current user's information, such as `Cookies`, `JwtBearer`, `OpenID Connect`, `Google` etc.
After authentication, we get a set of claims that can be issued using a trusted identity provider. A claim is a type/name-value pair representing the subject. The type property provides the semantic content of the claim, that is, it states what the claim is about.
The [`ICurrentUser`](https://docs.abp.io/en/abp/latest/CurrentUser) service of the ABP Framework provides a convenient way to access the current user's information from the claims.
The claim type is the key to getting the correct value of the current user, and we have a static `AbpClaimTypes` class that defines the names of the standard claims in the ABP Framework:
```cs
public static class AbpClaimTypes
{
public static string UserId { get; set; } = ClaimTypes.NameIdentifier;
public static string UserName { get; set; } = ClaimTypes.Name;
public static string Role { get; set; } = ClaimTypes.Role;
public static string Email { get; set; } = ClaimTypes.Email;
//...
}
```
As you can see, the default claim type of `AbpClaimTypes` comes from the [`System.Security.Claims.ClaimTypes`](https://learn.microsoft.com/en-us/dotnet/api/system.security.claims.claimtypes) class, which is the recommended practice in NET.
## Claim type in different authentication schemes
We usually see two types of claim types in our daily development. One of them is the [`System.Security.Claims.ClaimTypes`](https://learn.microsoft.com/en-us/dotnet/api/system.security.claims.claimtypes) and the other one is the `OpenId Connect` [standard claims](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims).
### ASP NET Core Identity
There is a [`ClaimsIdentityOptions`](https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.identity.claimsidentityoptions) property in the `IdentityOptions`, which can be used to configure the claim type:
| Property | Description |
|----------------------|---------------------------------------------------------------------------------------------------------------|
| EmailClaimType | Gets or sets the ClaimType used for the user email claim. Defaults to Email. |
| RoleClaimType | Gets or sets the ClaimType used for a Role claim. Defaults to Role. |
| SecurityStampClaimType | Gets or sets the ClaimType used for the security stamp claim. Defaults to "AspNet.Identity.SecurityStamp". |
| UserIdClaimType | Gets or sets the ClaimType used for the user identifier claim. Defaults to NameIdentifier. |
| UserNameClaimType | Gets or sets the ClaimType used for the user name claim. Defaults to Name. |
* The Identity creates a `ClaimsIdentity` object with the claim type that you have configured in the `ClaimsIdentityOptions` class.
* The ABP Framework configures it based on `AbpClaimTypes,` so usually you don't need to worry about it.
### JwtBearer/OpenID Connect Client
The `JwtBearer/OpenID Connect` gets claims from `id_token` or fetches user information from the `AuthServer`, and then maps/adds it to the current `ClaimsIdentity`.
To map the [standard claim](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims) type to the [`System.Security.Claims.ClaimTypes`](https://learn.microsoft.com/en-us/dotnet/api/system.security.claims.claimtypes) via [azure-activedirectory-identitymodel-extensions-for-dotnet](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet) library by default, which is maintained by the Microsoft team:
```cs
Dictionary<string, string> ClaimTypeMapping = new Dictionary<string, string>
{
{ "actort", ClaimTypes.Actor },
{ "birthdate", ClaimTypes.DateOfBirth },
{ "email", ClaimTypes.Email },
{ "family_name", ClaimTypes.Surname },
{ "gender", ClaimTypes.Gender },
{ "given_name", ClaimTypes.GivenName },
{ "nameid", ClaimTypes.NameIdentifier },
{ "sub", ClaimTypes.NameIdentifier },
{ "website", ClaimTypes.Webpage },
{ "unique_name", ClaimTypes.Name },
{ "oid", "http://schemas.microsoft.com/identity/claims/objectidentifier" },
{ "scp", "http://schemas.microsoft.com/identity/claims/scope" },
{ "tid", "http://schemas.microsoft.com/identity/claims/tenantid" },
{ "acr", "http://schemas.microsoft.com/claims/authnclassreference" },
{ "adfs1email", "http://schemas.xmlsoap.org/claims/EmailAddress" },
{ "adfs1upn", "http://schemas.xmlsoap.org/claims/UPN" },
{ "amr", "http://schemas.microsoft.com/claims/authnmethodsreferences" },
{ "authmethod", ClaimTypes.AuthenticationMethod },
{ "certapppolicy", "http://schemas.microsoft.com/2012/12/certificatecontext/extension/applicationpolicy" },
{ "certauthoritykeyidentifier", "http://schemas.microsoft.com/2012/12/certificatecontext/extension/authoritykeyidentifier" },
{ "certbasicconstraints", "http://schemas.microsoft.com/2012/12/certificatecontext/extension/basicconstraints" },
{ "certeku", "http://schemas.microsoft.com/2012/12/certificatecontext/extension/eku" },
{ "certissuer", "http://schemas.microsoft.com/2012/12/certificatecontext/field/issuer" },
{ "certissuername", "http://schemas.microsoft.com/2012/12/certificatecontext/field/issuername" },
{ "certkeyusage", "http://schemas.microsoft.com/2012/12/certificatecontext/extension/keyusage" },
{ "certnotafter", "http://schemas.microsoft.com/2012/12/certificatecontext/field/notafter" },
{ "certnotbefore", "http://schemas.microsoft.com/2012/12/certificatecontext/field/notbefore" },
{ "certpolicy", "http://schemas.microsoft.com/2012/12/certificatecontext/extension/certificatepolicy" },
{ "certpublickey", ClaimTypes.Rsa },
{ "certrawdata", "http://schemas.microsoft.com/2012/12/certificatecontext/field/rawdata" },
{ "certserialnumber", ClaimTypes.SerialNumber },
{ "certsignaturealgorithm", "http://schemas.microsoft.com/2012/12/certificatecontext/field/signaturealgorithm" },
{ "certsubject", "http://schemas.microsoft.com/2012/12/certificatecontext/field/subject" },
{ "certsubjectaltname", "http://schemas.microsoft.com/2012/12/certificatecontext/extension/san" },
{ "certsubjectkeyidentifier", "http://schemas.microsoft.com/2012/12/certificatecontext/extension/subjectkeyidentifier" },
{ "certsubjectname", "http://schemas.microsoft.com/2012/12/certificatecontext/field/subjectname" },
{ "certtemplateinformation", "http://schemas.microsoft.com/2012/12/certificatecontext/extension/certificatetemplateinformation" },
{ "certtemplatename", "http://schemas.microsoft.com/2012/12/certificatecontext/extension/certificatetemplatename" },
{ "certthumbprint", ClaimTypes.Thumbprint },
{ "certx509version", "http://schemas.microsoft.com/2012/12/certificatecontext/field/x509version" },
{ "clientapplication", "http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-client-application" },
{ "clientip", "http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-client-ip" },
{ "clientuseragent", "http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-client-user-agent" },
{ "commonname", "http://schemas.xmlsoap.org/claims/CommonName" },
{ "denyonlyprimarygroupsid", ClaimTypes.DenyOnlyPrimaryGroupSid },
{ "denyonlyprimarysid", ClaimTypes.DenyOnlyPrimarySid },
{ "denyonlysid", ClaimTypes.DenyOnlySid },
{ "devicedispname", "http://schemas.microsoft.com/2012/01/devicecontext/claims/displayname" },
{ "deviceid", "http://schemas.microsoft.com/2012/01/devicecontext/claims/identifier" },
{ "deviceismanaged", "http://schemas.microsoft.com/2012/01/devicecontext/claims/ismanaged" },
{ "deviceostype", "http://schemas.microsoft.com/2012/01/devicecontext/claims/ostype" },
{ "deviceosver", "http://schemas.microsoft.com/2012/01/devicecontext/claims/osversion" },
{ "deviceowner", "http://schemas.microsoft.com/2012/01/devicecontext/claims/userowner" },
{ "deviceregid", "http://schemas.microsoft.com/2012/01/devicecontext/claims/registrationid" },
{ "endpointpath", "http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-endpoint-absolute-path" },
{ "forwardedclientip", "http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-forwarded-client-ip" },
{ "group", "http://schemas.xmlsoap.org/claims/Group" },
{ "groupsid", ClaimTypes.GroupSid },
{ "idp", "http://schemas.microsoft.com/identity/claims/identityprovider" },
{ "insidecorporatenetwork", "http://schemas.microsoft.com/ws/2012/01/insidecorporatenetwork" },
{ "isregistereduser", "http://schemas.microsoft.com/2012/01/devicecontext/claims/isregistereduser" },
{ "ppid", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/privatepersonalidentifier" },
{ "primarygroupsid", ClaimTypes.PrimaryGroupSid },
{ "primarysid", ClaimTypes.PrimarySid },
{ "proxy", "http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-proxy" },
{ "pwdchgurl", "http://schemas.microsoft.com/ws/2012/01/passwordchangeurl" },
{ "pwdexpdays", "http://schemas.microsoft.com/ws/2012/01/passwordexpirationdays" },
{ "pwdexptime", "http://schemas.microsoft.com/ws/2012/01/passwordexpirationtime" },
{ "relyingpartytrustid", "http://schemas.microsoft.com/2012/01/requestcontext/claims/relyingpartytrustid" },
{ "role", ClaimTypes.Role },
{ "roles", ClaimTypes.Role },
{ "upn", ClaimTypes.Upn },
{ "winaccountname", ClaimTypes.WindowsAccountName },
};
```
#### Disable JwtBearer/OpenID Connect Client Claim Type Mapping
To turn off the claim type mapping, you can set the `MapInboundClaims` property of `JwtBearerOptions` or `OpenIdConnectOptions` to `false`. Then, you can get the original claim types from the token(`access_token` or `id_token`):
JWT Example:
```json
{
"iss": "https://localhost:44305/",
"exp": 1714466127,
"iat": 1714466127,
"aud": "MyProjectName",
"scope": "MyProjectName offline_access",
"sub": "ed7f5cfd-7311-0402-245c-3a123ff787f9",
"unique_name": "admin",
"preferred_username": "admin",
"given_name": "admin",
"role": "admin",
"email": "admin@abp.io",
"email_verified": "False",
"phone_number_verified": "False",
}
```
### OAuth2(Google, Facebook, Twitter, Microsoft) Extenal Login Client
The `OAuth2 handler` fetchs a JSON containing user information from the `OAuth2` server. The third-party provider issues the claim type based on their standard server and then maps/adds it to the current `ClaimsIdentity`. The ASP NET Core provides some built-in claim-type mappings for different providers as can be seen below examples:
**Example**: The `ClaimActions` property of the `GoogleOptions` maps the Google's claim types to [`System.Security.Claims.ClaimTypes`](https://learn.microsoft.com/en-us/dotnet/api/system.security.claims.claimtypes):
```cs
ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "id"); // v2
ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "sub"); // v3
ClaimActions.MapJsonKey(ClaimTypes.Name, "name");
ClaimActions.MapJsonKey(ClaimTypes.GivenName, "given_name");
ClaimActions.MapJsonKey(ClaimTypes.Surname, "family_name");
ClaimActions.MapJsonKey("urn:google:profile", "link");
ClaimActions.MapJsonKey(ClaimTypes.Email, "email");
```
**Example**: The `ClaimActions` property of the `FacebookOptions` maps the Facebook's claim types to [`System.Security.Claims.ClaimTypes`](https://learn.microsoft.com/en-us/dotnet/api/system.security.claims.claimtypes):
```cs
ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "id");
ClaimActions.MapJsonSubKey("urn:facebook:age_range_min", "age_range", "min");
ClaimActions.MapJsonSubKey("urn:facebook:age_range_max", "age_range", "max");
ClaimActions.MapJsonKey(ClaimTypes.DateOfBirth, "birthday");
ClaimActions.MapJsonKey(ClaimTypes.Email, "email");
ClaimActions.MapJsonKey(ClaimTypes.Name, "name");
ClaimActions.MapJsonKey(ClaimTypes.GivenName, "first_name");
ClaimActions.MapJsonKey("urn:facebook:middle_name", "middle_name");
ClaimActions.MapJsonKey(ClaimTypes.Surname, "last_name");
ClaimActions.MapJsonKey(ClaimTypes.Gender, "gender");
ClaimActions.MapJsonKey("urn:facebook:link", "link");
ClaimActions.MapJsonSubKey("urn:facebook:location", "location", "name");
ClaimActions.MapJsonKey(ClaimTypes.Locality, "locale");
ClaimActions.MapJsonKey("urn:facebook:timezone", "timezone");
```
### OpenIddict AuthServer
The `OpenIddict` uses the [standard claims](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims) as the claim type of the `id_token` or `access_token` and `UserInfo` endpoint response, etc.
* For JWT token, it also uses the [azure-activedirectory-identitymodel-extensions-for-dotnet](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet) to get the claims from the `id_token` or `access_token`.
* For reference token, it gets the claims from the `database`.
## Summary
Once you find the claims you received do not meet your expectations, follow the instructions above to troubleshoot the problem.
This article can help you understand the claim type in the ABP Framework and ASP NET Core.

85
docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/POST.md

@ -0,0 +1,85 @@
# Deploy Your ABP Framework MVC Project to Azure Container Apps
![](azure-container-abp.png)
In this article, we will show the seamless deployment of an ABP Framework MVC project to Azure Container Apps. enabling you to deploy and run containerized applications without the hassle of managing the infrastructure underneath. It provides an uncomplicated and cost-effective method for deploying and scaling your applications.
### Getting Started with ABP Framework MVC and Azure Container Apps
To get started, you will need an ABP Framework MVC project that you want to deploy. If you don't have one, you can [create a new project using the ABP CLI](https://docs.abp.io/en/abp/latest/Startup-Templates/Application). You will also need [an Azure subscription](https://azure.microsoft.com) and [an Azure SQL database](https://azure.microsoft.com/en-gb/products/azure-sql).
Before creating Azure container apps resources and deploying the ABP Framework MVC project, I show you how you can effortlessly create Docker images and push them to Docker Hub, leveraging the pre-configured Docker file and scripts that come with the ABP MVC framework.
### Creating a Docker Image for ABP Framework MVC
To create a Docker image for your ABP Framework MVC project, navigate to `etc/build/build-images-locally.ps1` and fix the script to match your Docker Hub username and image name. Then, run the script to build the Docker image locally.
![Build Docker Image](build-docker-image.png)
Next, check the Docker Hub repository to confirm that the image has been pushed successfully.
![Docker Hub Repository](docker-hub-repository.png)
### Deploying to Azure Container Apps
Now that you have Docker images for your ABP Framework MVC project, you can proceed to deploy it to Azure Container Apps. To do this, navigate to the Azure portal and create a new Azure Container Apps resource. Ypu will not need just an Azure Container Apps resource, but also an Azure Container Apps Job resource to migrate the database schema and seed data for your ABP Framework MVC project.
![Create Azure Container Apps](create-azure-container-apps.png)
#### Step 1: Deploy the Docker Image
Firstly, create a new Azure Container Apps resource without environment variables. You will need web url so that you can set it as an environment variable in the next step. Then, check the deployment status to confirm that the deployment was successful.
![Deploy Docker Image](deploy-docker-image.png)
#### Step 2: Migrate Database Schema and Seed Data
Secondly, create a new Azure Container Apps Job resource to migrate the database schema and seed data. You can do this by creating a new job with the following environment variables:
```text
ConnectionStrings__Default - Server=tcp:demoabpapp.database.windows.net,1433;Initial Catalog=mvcapppro;Persist Security Info=False;User ID=demoapppro;Password={your_password};MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;
OpenIddict__Applications__mvcapppro_Web__RootUrl - https://mvcwebapp.victoriousgrass-8b06438d.northeurope.azurecontainerapps.io
To get ConnectionStrings of Sql Database and url of the web app, you can navigate to the Azure portal and check the properties of the Azure SQL database and Azure Container Apps resource.
```
![Azure SQL Database Connection Strings](azure-sql-database-connection-strings.png)
![Create Azure Container Apps Job](create-azure-container-apps-job.png)
Finally, check the job status to confirm that the database migration and seeding were successful. You can connect to the Azure SQL database to verify that the schema and seed data have been applied.
![Check Job Status](check-job-status.png)
#### Step 3: Edit the Azure Container Apps Resource
After completing these steps, you have to edit the Azure Container Apps resource to add the required environment variables for your ABP Framework MVC project. You can do this by adding the following environment variables:
```text
App__SelfUrl - https://mvcwebapp.victoriousgrass-8b06438d.northeurope.azurecontainerapps.io
ASPNETCORE_URLS - http://+:80
AuthServer__Authority - https://mvcwebapp.victoriousgrass-8b06438d.northeurope.azurecontainerapps.io
ConnectionStrings__Default - Server=tcp:demoabpapp.database.windows.net,1433;Initial Catalog=mvcapppro;Persist Security Info=False;User ID=demoapppro;Password={your_password};MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;
```
![Add Environment Variables](add-environment-variables.png)
#### Step 4: Create a New Deployment
Once you have added the environment variables, save and create a new deployment to apply the changes. You can now access your ABP Framework MVC project running on Azure Container Apps by navigating to the URL provided in the environment variables.
![Access ABP Framework MVC Project](access-abp-framework-mvc-project.png)
You can see the Azure resources created for the ABP Framework MVC project deployment that includes the Azure Container Apps resource, Azure Container Apps Job resource, and Azure SQL database.
![Azure Resources](azure-resources.png)
### Conclusion
Azure Container Apps provides a simple and cost-effective way to deploy and scale your ABP Framework MVC projects without managing the underlying infrastructure. By following the steps outlined in this article, you can seamlessly deploy your ABP Framework MVC projects to Azure Container Apps and enjoy the benefits it offers.
I hope you found this article helpful. If you have any questions or feedback, please feel free to leave a comment below.

BIN
docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/access-abp-framework-mvc-project.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 625 KiB

BIN
docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/add-environment-variables.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 294 KiB

BIN
docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/azure-container-abp.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

BIN
docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/azure-resources.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 KiB

BIN
docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/azure-sql-database-connection-strings.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 203 KiB

BIN
docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/build-docker-image.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

BIN
docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/check-job-status.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 470 KiB

BIN
docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/create-azure-container-apps-job.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 KiB

BIN
docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/create-azure-container-apps.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

BIN
docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/deploy-docker-image.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 214 KiB

BIN
docs/en/Community-Articles/2024-05-07-Azure-Container-Apps-Deployment-with-ABP/docker-hub-repository.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
docs/en/Community-Articles/2024-05-07-using-fluent-validation-with-abp/images/adding-incorrect-data.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

BIN
docs/en/Community-Articles/2024-05-07-using-fluent-validation-with-abp/images/error.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
docs/en/Community-Articles/2024-05-07-using-fluent-validation-with-abp/images/validation.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

115
docs/en/Community-Articles/2024-05-07-using-fluent-validation-with-abp/post.md

@ -0,0 +1,115 @@
# Using FluentValidation with ABP Framework
## What is Validation? Why Do We Need to Validate?
Validation is checking whether data is valid or not. We can liken validations to the cell membrane of our application. Just as the cell does not want to let in harmful substances, we do not want to add erroneous data to the database, which is critical to our application. Validations allow data that follows the rules to reach the database. Data that does not comply with the rules will not access the database at all, and the operation will fail.
![Validation](./images/validation.png)
Validations make your application run more efficiently as they are not directly tied to the database. They should be implemented across various layers of the application, including the UI, backend, and database, to prevent malicious users from bypassing these checks. Fluent validation is frequently employed for creating backend validations.
## What is Fluent Validation?
Fluent validation is a library for checking whether data is valid or not. Fluent validation can be applied to your code in a fluent and understandable way.
## Why We Should Use Fluent Validation?
Fluent Validation allows you to define your validation rules in a clear and flexible way. This means you can comfortably handle complex validation scenarios in your code. This makes your development process much more manageable. The readability that Fluent Validation offers really makes things easier. Having a clear understanding of what your validation rules do is a huge advantage when working on your code. In short, your code is cleaner and clearer. Fluent Validation is also very functional in terms of testability. By defining your validation rules in separate classes, you can easily test and maintain these rules. Fluent Validation is a widely used validation library on the .NET platform. As such, it has become a common standard among .NET developers. This provides advantages in terms of community support and compatibility. So, using Fluent Validation simplifies your development process by making your code more understandable, manageable and testable.
In this section, I will show you how to use FluentValidation library within an ABP-based application. Therefore, I assume that you have an ABP-based application that has already been created. If you haven't created an ABP-based application yet, please follow the [Getting Started documentation](https://docs.abp.io/en/abp/latest/Getting-Started-Create-Solution?UI=MVC&DB=EF&Tiered=No).
Using Fluent validation with Abp is quite simple. Open a command line window in the folder of the project (.csproj file) and type the following command:
```bash
abp add-package Volo.Abp.FluentValidation
```
If you have not created your abp project, review the [steps to create](https://docs.abp.io/en/abp/latest/Tutorials/Todo/Overall) it now.
Create the `Product` entity as below:
````csharp
public class Product: FullAuditedAggregateRoot<Guid>
{
public string Name { get; set; } = string.Empty;
public decimal Price { get; set; }
public int Stock { get; set; }
public string? LicenseKey { get; set; }
}
````
You must have ProductCreateDto :
````csharp
public class ProductCreateDto
{
public string Name { get; set; }
public decimal Price { get; set; }
public int Stock { get; set; }
public string? LicenseKey { get; set; }
}
````
Create the `ProductCreateDtoValidator` class in the **Products** folder in the `Application.Contracts` project:
````csharp
public class ProductCreateDtoValidator :AbstractValidator<ProductCreateDto>
{
public ProductCreateDtoValidator()
{
RuleFor(p=>p.Name).
NotEmpty().
WithMessage("Product name cannot be empty");
RuleFor(p=>p.Name).
MinimumLength(3).
MaximumLength(100).
WithMessage("Product name must be between 3 and 100 characters");
RuleFor(p => p.Stock).
GreaterThanOrEqualTo(0).
WithMessage("Product stock should not be negative");
RuleFor(p => p.Price).
GreaterThanOrEqualTo(0).
WithMessage("Product Price should not be negative");
}
}
````
The validator class you create should inherit from `AbstractValidator`. You should give `AbstractValidator` the class you want to validate generically. You have to create a constructor method. You must write the code in this constructor method. Fluent validation provides you with ready-made methods that you can use to write validations very easily.
The **RuleFor** method allows you to write a validation rule. You must specify in the parameter for which property you want to write a validation rule.
With the **NotEmpty** method you can specify that a property cannot be null.
With **MinimumLength** and **MaximumLength** you can specify the minimum and maximum number of characters the property can take.
With the **GreaterThanOrEqualTo** method you can specify that the value of the property must be greater than or equal to the value entered as a parameter.
**WithMessage** method you can specify the message to be sent when the validation fails.
You can add a method to write your own customized validation code. For example, let's write the code that requires the license key field to contain the word “key”.
````csharp
private bool ContainsKey(string arg)
{
return arg.IndexOf("key", StringComparison.OrdinalIgnoreCase) >= 0;
}
````
Add the code to the constructor to use this method:
````csharp
RuleFor(p => p.LicenseKey).
Must(ContainsKey).
WithMessage("Product license key must contain the word 'key'");
````
Try to add data that does not meet the validation rules
![Adding Incorrect Data](./images/adding-incorrect-data.png)
If one of the validation rules does not meet the rules, then the following error will be received for the custom rule that we defined:
![Error](./images/error.png)
For more information on fluent validation with abp framework, see the [documentation](https://docs.abp.io/en/abp/latest/FluentValidation)
For more information on fluent validation, see the [documentation](https://docs.fluentvalidation.net/en/latest/) 

336
docs/en/Community-Articles/2024-05-10-Sentiment-Analysis-within-ABP-Based-Application/POST.md

@ -0,0 +1,336 @@
# Sentiment Analysis Within ABP-Based Application
In this article, first I will briefly explain what sentiment analysis is and then show you how you can apply sentiment analysis in an ABP-Based application (or any kind of .NET application).
We will use ML.NET Framework, which is an open-source machine learning framework created by the dotnet team and also we will create a layered ABP Solution by using the application template and finally we will use CMS Kit's Comment Feature and extend its behavior by adding spam detection while creating or updating a comment, at that point we will make sentiment analysis.
## Sentiment Analysis
[Sentiment Analysis (or opinion mining)](https://en.wikipedia.org/wiki/Sentiment_analysis) refers to determining the emotion from the given input. The primary goal of sentiment analysis is to identify, extract, and categorize (positive, negative, or neutral) the sentiments expressed in textual data.
To understand it better, let's check the following figure and examine the comments:
![](sentiment-analysis.png)
* If you look at these comments, you will notice that comments have ratings and it's easy to understand the emotion or thoughts of the users who commented about the related product.
* But even if there was not any rating specified for the given comments we still can get the emotion of the users. Because, as you can see, the comments specified some obvious words that express emotions, for example, in the first comment, the user says **he/she liked the product**, **it's easy to use** and **its battery is good**, and therefore this is obviously a positive comment.
* On the other hand, if we look at the second comment, we will notice some negative statements such as **useless phone**, **cannot maintain any data connection** and the user suggests **do not buy this phone**. Actually, this is what sentiment analysis is all about, abstracting the emotion from a given input, it's comment in that case but it can be any kind of input or input-group.
## Demo: Spam Detection (Applying Sentiment Analysis)
> You can get the source code of the demo from [https://github.com/EngincanV/SentimentAnalysisDemo](https://github.com/EngincanV/SentimentAnalysisDemo).
In this demo application, we will create an [ABP-based application](https://docs.abp.io/en/abp/8.1/Startup-Templates/Application) and integrate the [ABP's CMS Kit Module's Comment Feature](https://docs.abp.io/en/abp/latest/Modules/Cms-Kit/Comments), which provides a comment system to add a comment to any kind of resource, such as blog posts or products.
By default, CMS Kit's Comment Feature does not provide spam detection and therefore in this sample application, we will add [spam detection](https://github.com/EngincanV/SentimentAnalysisDemo/blob/master/src/SentimentAnalysisDemo.Application/ML/SpamDetector.cs) while creating or updating a comment. Thus, whenever a comment is being added or updated, the spam detection service will validate the comment and reject it if it contains spam content otherwise it will make the other validations and save the comment:
![](sentiment-analysis-steps.png)
To get started, we will first create an application, and add the CMS Kit Module to the solution and then we will enable the Comment Feature of the CMS Kit Module, and finally, we will add the Comment Component to the homepage and add spam detection by extending the behavior. Let's start with creating the application!
### Creating an ABP-Based Application
You can use the following command to create a layered ABP solution (with MongoDB as the database option):
```bash
abp new SentimentAnalysisDemo -t app -d mongodb --version 8.1.1
```
### Installing the CMS Kit Module
After creating the project, we can add the CMS Kit module to our project. [ABP CLI](https://docs.abp.io/en/abp/latest/CLI) provides the `add-module` command to install a specific module to a solution.
You can use the following command to install the CMS Kit module into your application (run this command in the solution directory):
```bash
abp add-module Volo.CmsKit --skip-db-migrations
```
After this command is executed, all related CMS Kit packages will be added to the correct layers and then you can enable any CMS Kit feature you want.
### Enabling the Comment Feature
By default, CMS Kit features are disabled. Therefore, you need to enable the features you want, before starting to use it. You can either enable all of them or enable them one by one. In our demo application, we only need the **Comment Feature**, therefore we can only enable it.
To enable the Comment Feature, you can open the `SentimentAnalysisDemoGlobalFeatureConfigurator` class (under the `*.Domain.Shared` project) and update it as follows:
```csharp
using Volo.Abp.GlobalFeatures;
using Volo.Abp.Threading;
namespace SentimentAnalysisDemo;
public static class SentimentAnalysisDemoGlobalFeatureConfigurator
{
private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner();
public static void Configure()
{
OneTimeRunner.Run(() =>
{
GlobalFeatureManager.Instance.Modules.CmsKit(cmsKit =>
{
cmsKit.Comments.Enable();
});
});
}
}
```
After enabling the feature, now we can make the final configurations and directly use it in our application.
### Configurations for Comment Feature
Open the `SentimentAnalysisDemoDomainModule` class and add the following code-block into the `ConfigureServices` method:
```csharp
Configure<CmsKitCommentOptions>(options =>
{
options.EntityTypes.Add(new CommentEntityTypeDefinition("Comment"));
options.IsRecaptchaEnabled = true;
});
```
Here, we simply defining what should be the entity-type name of our comment and also enable the reCaptcha for the comment system. After this configuration, now we can open the `Index.cshtml` file in the `*.Web` project and invoke the `CommentingViewComponent` as below:
```html
@page
@using Microsoft.AspNetCore.Mvc.Localization
@using SentimentAnalysisDemo.Localization
@using Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.Commenting
@model SentimentAnalysisDemo.Web.Pages.IndexModel
<div class="container">
<h5 class="display-5">Comments:</h5>
@await Component.InvokeAsync(typeof(CommentingViewComponent), new
{
entityType = "Comment",
entityId = "SentimentAnalysisDemo",
isReadOnly = false
})
</div>
```
After adding the related component, now you can run the web project and see the comment component if you want.
### Applying Sentiment Analysis (Creating the Spam Detection Service)
By default, CMS Kit's Comment Feature does not provide a spam detection system. In this demo application, we will override the `CommentPublicAppService`'s `CreateAsync` and `UpdateAsync` methods and then will add the spam detection control whenever a new comment has been submitted or an existing one is being updated.
To override the `CommentPublicAppService` and extend its use-case implementations, create a `MyCommentAppService` class and update its content as below:
```csharp
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using SentimentAnalysisDemo.ML;
using Volo.Abp.DependencyInjection;
using Volo.Abp.EventBus.Distributed;
using Volo.CmsKit.Comments;
using Volo.CmsKit.Public.Comments;
using Volo.CmsKit.Users;
namespace SentimentAnalysisDemo.Volo.CmsKit.Public.Comments;
[Dependency(ReplaceServices = true)]
[ExposeServices(typeof(ICommentPublicAppService), typeof(CommentPublicAppService), typeof(MyCommentAppService))]
public class MyCommentAppService : CommentPublicAppService
{
protected ISpamDetector SpamDetector { get; }
public MyCommentAppService(
ICommentRepository commentRepository,
ICmsUserLookupService cmsUserLookupService,
IDistributedEventBus distributedEventBus,
CommentManager commentManager,
IOptionsSnapshot<CmsKitCommentOptions> cmsCommentOptions,
ISpamDetector spamDetector
)
: base(commentRepository, cmsUserLookupService, distributedEventBus, commentManager, cmsCommentOptions)
{
SpamDetector = spamDetector;
}
public override async Task<CommentDto> CreateAsync(string entityType, string entityId, CreateCommentInput input)
{
//Check message: spam or ham.
await SpamDetector.CheckAsync(input.Text);
return await base.CreateAsync(entityType, entityId, input);
}
public override async Task<CommentDto> UpdateAsync(Guid id, UpdateCommentInput input)
{
//Check message: spam or ham.
await SpamDetector.CheckAsync(input.Text);
return await base.UpdateAsync(id, input);
}
}
```
Here, we simply just inject the `ISpamDetector` service, which we will create in a minute, and use its `CheckAsync` method to make a spam check before the comment is created or updated.
Now, we can create the `ISpamDetector` service in the `*.Application.Contracts` project as follows:
```csharp
using System.Threading.Tasks;
namespace SentimentAnalysisDemo.ML;
public interface ISpamDetector
{
Task CheckAsync(string text);
}
```
Then, we can create the `SpamDetector` and implement the `ISpamDetector` interface (in the `*.Application` project):
```csharp
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.ML;
using SentimentAnalysisDemo.ML.Model;
using Volo.Abp;
using Volo.Abp.DependencyInjection;
namespace SentimentAnalysisDemo.ML;
public class SpamDetector : ISpamDetector, ITransientDependency
{
public async Task CheckAsync(string text)
{
//check if the text contains a spam content or not...
}
}
```
The `CheckAsync` method is where we need to make the sentiment analysis and detect if the comment contains spam content or not. If it's spam, then we should throw a [UserFriendlyException](https://docs.abp.io/en/abp/latest/Exception-Handling#user-friendly-exception) and notify the user that the comment should be updated and should not contain any spam content.
#### Spam Detection
Before, making the spam check, we should have a dataset to train a machine-learning model and add `Microsoft.ML` package into our project. For that purpose, I searched in [Kaggle](https://www.kaggle.com/) for spam datasets, found the **Spam-Mail-Detection-Dataset** from Kaggle, and downloaded the csv file to use in my application. Therefore, [you should also download the dataset from the link and put it under the **/ML/Data/spam_data.csv** directory of the `*.Web` project](https://github.com/EngincanV/SentimentAnalysisDemo/blob/master/src/SentimentAnalysisDemo.Web/ML/Data/spam_data.csv).
Here is what our dataset looks like (**0 -> not spam / 1 -> spam**):
| Category | Message |
|----------|---------|
| 0 | Is that seriously how you spell his name? |
| 1 | Free entry in 2 a wkly comp to win FA Cup final tkts 21st May 2005. Text FA to 87121 to receive entry question(std txt rate)T&C's apply 08452810075over18's |
| . | . |
| . | . |
| . | . |
> **Note:** This dataset is not ready-to use in a real-world solution. It's for mail spam detection but for the simplicity of the sample, it's not important and can be used for development purposes.
After, downloading the dataset and putting it in the directory of **/ML/Data**, now we can add the `Microsoft.ML` package into our `*.Application` project:
```bash
dotnet add package Microsoft.ML
```
Finally, we can implement the `CheckAsync` method and use sentiment analysis to make spam checks as follows:
```csharp
public async Task CheckAsync(string text)
{
var dataPath = Path.Combine(Environment.CurrentDirectory, "ML", "Data", "spam_data.csv");
var mlContext = new MLContext();
//Step 1: Load Data 👇
IDataView dataView = mlContext.Data.LoadFromTextFile<SentimentAnalyzeInput>(dataPath, hasHeader: true, separatorChar: ',');
//Step 2: Split data to train-test data 👇
DataOperationsCatalog.TrainTestData trainTestSplit = mlContext.Data.TrainTestSplit(dataView, testFraction: 0.2);
IDataView trainingData = trainTestSplit.TrainSet; //80% of the data.
IDataView testData = trainTestSplit.TestSet; //20% of the data.
//Step 3: Common data process configuration with pipeline data transformations + choose and set the training algorithm 👇
var estimator = mlContext.Transforms.Text.FeaturizeText(outputColumnName: "Features", inputColumnName: nameof(SentimentAnalyzeInput.Message))
.Append(mlContext.BinaryClassification.Trainers.SdcaLogisticRegression(labelColumnName: "Label", featureColumnName: "Features"));
//Step 4: Train the model 👇
ITransformer model = estimator.Fit(trainingData);
//Step 5: Predict 👇
var sentimentAnalyzeInput = new SentimentAnalyzeInput
{
Message = text
};
var predictionEngine = mlContext.Model.CreatePredictionEngine<SentimentAnalyzeInput, SentimentAnalyzeResult>(model);
var result = predictionEngine.Predict(sentimentAnalyzeInput);
if (IsSpam(result))
{
throw new UserFriendlyException("Spam detected! Please update the message!");
}
}
private static bool IsSpam(SentimentAnalyzeResult result)
{
//1 -> spam / 0 -> ham (for 'Prediction' column)
return result is { Prediction: true, Probability: >= 0.5f };
}
```
Here, we have done the following things:
1. **First, we loaded the data**: For that reason, we created a `MLContext` object, which is a main class for all ML.NET operations. Then, we used its `LoadFromTextFile` method and specified the dataset path in our application. Also, we mapped the dataset columns to the `SentimentAnalyzeInput` class, which we will create later on.
2. **For the second step, we split the data as training and testing data**: To be able to train a machine learning model and then evaluate its accuracy, we should not use all the data for training purposes, instead, we should split the data as training and testing data and after training the model, compare the training data accuracy with the testing data.
3. **For the third step, we should make data transformation, convert the text-based data into numeric vectors and then choose a training algorithm**: After splitting the data for training and testing purposes, now we can apply some data transformations for the *Message* column in our dataset. Because, as you would see, messages are text-based inputs and machine-learning algorithms work best with the numeric vectors. So, we are making data transformations and representing the data as numeric values. Then, we can apply `BinaryClassification` with the **SdcaLogicticRegression** algorithm to our training data.
4. **Train the model**: Since we make the data transformations and chose the correct algorithm for our model, now we can train the model.
5. **Predict the sample data**: Finally, we can pass a comment to this method and make spam check and either approve our reject the comment according to the predicted result. (To make predictions, we need to create a **PredictionEngine** and get the final results in the output class that we specified, `SentimentAnalyzeResult` in our example)
Let's create the `SentimentAnalyzeInput` and `SentimentAnalyzeResult` classes as follows.
**SentimentAnalyzeInput.cs:**
```csharp
using Microsoft.ML.Data;
namespace SentimentAnalysisDemo.ML.Model;
public class SentimentAnalyzeInput
{
[LoadColumn(0), ColumnName("Label")]
public bool Category { get; set; }
[LoadColumn(1), ColumnName("Message")]
public string Message { get; set; }
}
```
**SentimentAnalyzeResult.cs:**
```csharp
using Microsoft.ML.Data;
namespace SentimentAnalysisDemo.ML.Model;
public class SentimentAnalyzeResult
{
[ColumnName("PredictedLabel")]
public bool Prediction { get; set; }
public float Probability { get; set; }
public float Score { get; set; }
}
```
Then, finally we can run the application to see the final results:
![](demo.gif)
## Conclusion
In this article, I briefly explain what sentiment analysis is, created a sample ABP-based application, integrated the CMS Kit Module and finally, applied sentiment analysis to make spam checks whenever a new comment has been submitted or updated. You can get the source code of the demo from [https://github.com/EngincanV/SentimentAnalysisDemo](https://github.com/EngincanV/SentimentAnalysisDemo)
Thanks for reading :)

BIN
docs/en/Community-Articles/2024-05-10-Sentiment-Analysis-within-ABP-Based-Application/cover-image.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 348 KiB

BIN
docs/en/Community-Articles/2024-05-10-Sentiment-Analysis-within-ABP-Based-Application/demo.gif

Binary file not shown.

After

Width:  |  Height:  |  Size: 774 KiB

BIN
docs/en/Community-Articles/2024-05-10-Sentiment-Analysis-within-ABP-Based-Application/sentiment-analysis-steps.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

BIN
docs/en/Community-Articles/2024-05-10-Sentiment-Analysis-within-ABP-Based-Application/sentiment-analysis.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

3
docs/pt-BR/AspNetCore/Auto-API-Controllers.md

@ -0,0 +1,3 @@
Este documento foi movido.
[Clique para navegar até o documento Auto API Controllers](../API/Auto-API-Controllers.md)

3
docs/pt-BR/AspNetCore/Bundling-Minification.md

@ -0,0 +1,3 @@
Este documento foi movido.
[Clique para navegar até o documento de Bundling & Minification do ASP.NET Core MVC](../UI/AspNetCore/Bundling-Minification.md)

3
docs/pt-BR/AspNetCore/Client-Side-Package-Management.md

@ -0,0 +1,3 @@
Este documento foi movido.
[Clique para navegar até o documento de Gerenciamento de Pacotes do Lado do Cliente do ASP.NET Core MVC](../UI/AspNetCore/Client-Side-Package-Management.md)

3
docs/pt-BR/AspNetCore/Dynamic-CSharp-API-Clients.md

@ -0,0 +1,3 @@
Este documento foi movido.
[Clique para navegar até o documento Dynamic C# API Clients](../API/Dynamic-CSharp-API-Clients.md)

3
docs/pt-BR/AspNetCore/Tag-Helpers/Dynamic-Forms.md

@ -0,0 +1,3 @@
Este documento foi movido.
[Clique para navegar até o documento de Formulários Dinâmicos](../../UI/AspNetCore/Tag-Helpers/Dynamic-Forms.md)

3
docs/pt-BR/AspNetCore/Tag-Helpers/Index.md

@ -0,0 +1,3 @@
Este documento foi movido.
[Clique para navegar até o documento ABP Tag Helpers](../../UI/AspNetCore/Tag-Helpers/Index.md)

3
docs/pt-BR/AspNetCore/Theming.md

@ -0,0 +1,3 @@
Este documento foi movido.
[Clique para navegar até o documento de Temas](../UI/AspNetCore/Theming.md)

3
docs/pt-BR/AspNetCore/Widgets.md

@ -0,0 +1,3 @@
Este documento foi movido.
[Clique para navegar até o documento Widgets](../UI/AspNetCore/Widgets.md)

391
docs/pt-BR/Audit-Logging.md

@ -1,3 +1,390 @@
# Audit Logging
# Registro de Auditoria
Façam
[Wikipedia](https://en.wikipedia.org/wiki/Audit_trail): "*Um rastro de auditoria (também chamado de **log de auditoria**) é um registro cronológico relevante para a segurança, conjunto de registros e/ou destino e origem de registros que fornecem evidências documentais da sequência de atividades que afetaram a qualquer momento uma operação, procedimento ou evento específico*".
O ABP Framework fornece um **sistema de registro de auditoria extensível** que automatiza o registro de auditoria por **convenção** e fornece **pontos de configuração** para controlar o nível dos logs de auditoria.
Um **objeto de log de auditoria** (consulte a seção Objeto de Log de Auditoria abaixo) é tipicamente criado e salvo por solicitação da web. Ele inclui;
* Detalhes da **solicitação e resposta** (como URL, método Http, informações do navegador, código de status HTTP... etc.).
* **Ações realizadas** (ações do controlador e chamadas de métodos de serviço de aplicação com seus parâmetros).
* **Mudanças de entidade** ocorridas na solicitação da web.
* Informações de **exceção** (se houve um erro durante a execução da solicitação).
* **Duração da solicitação** (para medir o desempenho da aplicação).
> Os [modelos de inicialização](Startup-Templates/Index.md) são configurados para o sistema de registro de auditoria, o que é adequado para a maioria das aplicações. Use este documento para um controle detalhado sobre o sistema de log de auditoria.
### Suporte do Provedor de Banco de Dados
* Totalmente suportado pelo provedor [Entity Framework Core](Entity-Framework-Core.md).
* O log de alterações de entidade não é suportado pelo provedor [MongoDB](MongoDB.md). Outros recursos funcionam conforme o esperado.
## UseAuditing()
O middleware `UseAuditing()` deve ser adicionado ao pipeline de solicitações do ASP.NET Core para criar e salvar os logs de auditoria. Se você criou suas aplicações usando [os modelos de inicialização](Startup-Templates/Index.md), ele já está adicionado.
## AbpAuditingOptions
`AbpAuditingOptions` é o principal [objeto de opções](Options.md) para configurar o sistema de log de auditoria. Você pode configurá-lo no método `ConfigureServices` do seu [módulo](Module-Development-Basics.md):
````csharp
Configure<AbpAuditingOptions>(options =>
{
options.IsEnabled = false; //Desativa o sistema de auditoria
});
````
Aqui, uma lista das opções que você pode configurar:
* `IsEnabled` (padrão: `true`): Uma chave raiz para habilitar ou desabilitar o sistema de auditoria. Outras opções não são usadas se esse valor for `false`.
* `HideErrors` (padrão: `true`): O sistema de log de auditoria oculta e escreve [logs](Logging.md) regulares se ocorrer algum erro ao salvar os objetos de log de auditoria. Se salvar os logs de auditoria for crítico para o seu sistema, defina isso como `false` para lançar uma exceção em caso de ocultação de erros.
* `IsEnabledForAnonymousUsers` (padrão: `true`): Se você deseja escrever logs de auditoria apenas para os usuários autenticados, defina isso como `false`. Se você salvar logs de auditoria para usuários anônimos, verá `null` para os valores de `UserId` desses usuários.
* `AlwaysLogOnException` (padrão: `true`): Se definido como verdadeiro, sempre salva o log de auditoria em caso de exceção/erro sem verificar outras opções (exceto `IsEnabled`, que desativa completamente o registro de auditoria).
* `IsEnabledForIntegrationService` (padrão: `false`): O Registro de Auditoria é desativado para [serviços de integração](Integration-Services.md) por padrão. Defina essa propriedade como `true` para habilitá-la.
* `IsEnabledForGetRequests` (padrão: `false`): As solicitações HTTP GET normalmente não devem fazer nenhuma alteração no banco de dados e o sistema de log de auditoria não salva objetos de log de auditoria para solicitações GET. Defina isso como `true` para habilitá-lo também para as solicitações GET.
* `DisableLogActionInfo` (padrão: `false`): Se definido como verdadeiro, não registrará mais `AuditLogActionInfo`.
* `ApplicationName`: Se várias aplicações estiverem salvando logs de auditoria em um único banco de dados, defina essa propriedade com o nome da sua aplicação, para que você possa distinguir os logs de diferentes aplicações. Se você não definir, ele será definido a partir do valor `IApplicationInfoAccessor.ApplicationName`, que é o nome da assembly de entrada por padrão.
* `IgnoredTypes`: Uma lista de `Type`s a serem ignorados para o registro de auditoria. Se for um tipo de entidade, as alterações para esse tipo de entidades não serão salvas. Esta lista também é usada ao serializar os parâmetros de ação.
* `EntityHistorySelectors`: Uma lista de seletores usados para determinar se um tipo de entidade é selecionado para salvar a alteração da entidade. Consulte a seção abaixo para detalhes.
* `SaveEntityHistoryWhenNavigationChanges` (padrão: `true`): Se definido como verdadeiro, salvará as alterações da entidade no log de auditoria quando houver alterações em propriedades de navegação.
* `Contributors`: Uma lista de implementações de `AuditLogContributor`. Um contribuidor é uma forma de estender o sistema de log de auditoria. Consulte a seção "Contribuidores de Log de Auditoria" abaixo.
* `AlwaysLogSelectors`: Uma lista de seletores para salvar os logs de auditoria para os critérios correspondentes.
### Seletores de Histórico de Entidade
Salvar todas as alterações de todas as suas entidades exigiria muito espaço no banco de dados. Por esse motivo, **o sistema de log de auditoria não salva nenhuma alteração para as entidades a menos que você configure explicitamente**.
Para salvar todas as alterações de todas as entidades, simplesmente use o método de extensão `AddAllEntities()`.
````csharp
Configure<AbpAuditingOptions>(options =>
{
options.EntityHistorySelectors.AddAllEntities();
});
````
`options.EntityHistorySelectors` na verdade é uma lista de predicados de tipo. Você pode escrever uma expressão lambda para definir seu filtro.
O seletor de exemplo abaixo faz o mesmo do método de extensão `AddAllEntities()` definido acima:
````csharp
Configure<AbpAuditingOptions>(options =>
{
options.EntityHistorySelectors.Add(
new NamedTypeSelector(
"MeuSeletorNome",
type =>
{
if (typeof(IEntity).IsAssignableFrom(type))
{
return true;
}
else
{
return false;
}
}
)
);
});
````
A condição `typeof(IEntity).IsAssignableFrom(type)` será `true` para qualquer classe que implemente a interface `IEntity` (tecnicamente, todas as entidades em sua aplicação). Você pode verificar condicionalmente e retornar `true` ou `false` com base em sua preferência.
`options.EntityHistorySelectors` é uma forma flexível e dinâmica de selecionar as entidades para o registro de auditoria. Outra forma é usar os atributos `Audited` e `DisableAuditing` por entidade.
## AbpAspNetCoreAuditingOptions
`AbpAspNetCoreAuditingOptions` é o [objeto de opções](Options.md) para configurar o registro de auditoria na camada ASP.NET Core. Você pode configurá-lo no método `ConfigureServices` do seu [módulo](Module-Development-Basics.md):
````csharp
Configure<AbpAspNetCoreAuditingOptions>(options =>
{
options.IgnoredUrls.Add("/produtos");
});
````
`IgnoredUrls` é a única opção. É uma lista de prefixos de URLs ignorados. No exemplo anterior, todas as URLs que começam com `/produtos` serão ignoradas para o registro de auditoria.
## Habilitando/Desabilitando o Registro de Auditoria para Serviços
### Habilitar/Desabilitar para Controladores e Ações
Todas as ações do controlador são registradas por padrão (consulte `IsEnabledForGetRequests` acima para solicitações GET).
Você pode usar o `[DisableAuditing]` para desativá-lo para um tipo de controlador específico:
````csharp
[DisableAuditing]
public class HomeController : AbpController
{
//...
}
````
Use `[DisableAuditing]` para qualquer ação para controlá-la no nível da ação:
````csharp
public class HomeController : AbpController
{
[DisableAuditing]
public async Task<ActionResult> Home()
{
//...
}
public async Task<ActionResult> OutraAcaoRegistrada()
{
//...
}
}
````
### Habilitar/Desabilitar para Serviços de Aplicação e Métodos
As chamadas de métodos de [serviço de aplicação](Application-Services.md) também são incluídas no log de auditoria por padrão. Você pode usar o `[DisableAuditing]` no nível do serviço ou do método.
#### Habilitar/Desabilitar para Outros Serviços
O registro de auditoria de ação pode ser habilitado para qualquer tipo de classe (registrado e resolvido da [injeção de dependência](Dependency-Injection.md)) enquanto é habilitado apenas para os controladores e os serviços de aplicação por padrão.
Use `[Audited]` e `[DisableAuditing]` para qualquer classe ou método que precisa ser registrado no log de auditoria. Além disso, sua classe pode (direta ou implicitamente) implementar a interface `IAuditingEnabled` para habilitar o registro de auditoria para essa classe por padrão.
### Habilitar/Desabilitar para Entidades e Propriedades
Uma entidade é ignorada no registro de alteração de entidade nos seguintes casos;
* Se você adicionar um tipo de entidade às `AbpAuditingOptions.IgnoredTypes` (como explicado anteriormente), ele é completamente ignorado no sistema de registro de auditoria.
* Se o objeto não for uma [entidade](Entities.md) (não implementa `IEntity` diretamente ou implicitamente - Todas as entidades implementam essa interface por padrão).
* Se o tipo de entidade não for público.
Caso contrário, você pode usar `Audited` para habilitar o registro de alteração de entidade para uma entidade:
````csharp
[Audited]
public class MinhaEntidade : Entity<Guid>
{
//...
}
````
Ou desativá-lo para uma entidade:
````csharp
[DisableAuditing]
public class MinhaEntidade : Entity<Guid>
{
//...
}
````
Desativar o registro de auditoria pode ser necessário apenas se a entidade estiver sendo selecionada pelos `AbpAuditingOptions.EntityHistorySelectors` que foram explicados anteriormente.
Você pode desativar o registro de auditoria apenas para algumas propriedades de suas entidades para um controle detalhado sobre o registro de auditoria:
````csharp
[Audited]
public class MeuUsuario : Entity<Guid>
{
public string Nome { get; set; }
public string Email { get; set; }
[DisableAuditing] //Ignora a Senha no registro de auditoria
public string Senha { get; set; }
}
````
O sistema de log de auditoria salvará as alterações para a entidade `MeuUsuario` enquanto ignora a propriedade `Senha`, que pode ser perigosa de salvar por motivos de segurança.
Em alguns casos, você pode querer salvar apenas algumas propriedades de suas entidades e ignorar todas as outras. Escrever `[DisableAuditing]` para todas as outras propriedades seria tedioso. Em tais casos, use `[Audited]` apenas para as propriedades desejadas e marque a entidade com o atributo `[DisableAuditing]`:
````csharp
[DisableAuditing]
public class MeuUsuario : Entity<Guid>
{
[Audited] //Apenas registra a alteração do Nome
public string Nome { get; set; }
public string Email { get; set; }
public string Senha { get; set; }
}
````
## IAuditingStore
`IAuditingStore` é uma interface usada para salvar os objetos de log de auditoria (explicados abaixo) pelo Framework ABP. Se você precisa salvar os objetos de log de auditoria em um armazenamento de dados personalizado, pode implementar o `IAuditingStore` em sua própria aplicação e substituir usando o [sistema de injeção de dependência](Dependency-Injection.md).
`SimpleLogAuditingStore` é usado se nenhum armazenamento de auditoria estiver registrado. Ele simplesmente escreve o objeto de auditoria no sistema padrão de [logging](Logging.md).
[O Módulo de Registro de Auditoria](Modules/Audit-Logging.md) foi configurado nos [modelos de inicialização](Startup-Templates/Index.md) para salvar objetos de log de auditoria em um banco de dados (ele suporta vários provedores de banco de dados). Portanto, na maioria das vezes, você não precisa se preocupar com como o `IAuditingStore` foi implementado e usado.
## Objeto de Log de Auditoria
Um **objeto de log de auditoria** é criado para cada **solicitação web** por padrão. Um objeto de log de auditoria pode ser representado pelo seguinte diagrama de relação:
![**auditlog-object-diagram**](images/auditlog-object-diagram.png)
* **AuditLogInfo**: O objeto raiz com as seguintes propriedades:
* `ApplicationName`: Quando você salva logs de auditoria de diferentes aplicações no mesmo banco de dados, essa propriedade é usada para distinguir os logs das aplicações.
* `UserId`: Id do usuário atual, se o usuário estiver logado.
* `UserName`: Nome do usuário atual, se o usuário estiver logado (esse valor está aqui para não depender do módulo/sistema de identidade para pesquisa).
* `TenantId`: Id do locatário atual, para uma aplicação multi-locatário.
* `TenantName`: Nome do locatário atual, para uma aplicação multi-locatário.
* `ExecutionTime`: O momento em que este objeto de log de auditoria foi criado.
* `ExecutionDuration`: Duração total da execução da solicitação, em milissegundos. Isso pode ser usado para observar o desempenho da aplicação.
* `ClientId`: Id do cliente atual, se o cliente estiver autenticado. Um cliente é geralmente uma aplicação de terceiros que usa o sistema por meio de uma API HTTP.
* `ClientName`: Nome do cliente atual, se disponível.
* `ClientIpAddress`: Endereço IP do cliente/dispositivo do usuário.
* `CorrelationId`: Id de [Correlação Atual](CorrelationId.md). O Id de correlação é usado para relacionar os logs de auditoria escritos por diferentes aplicações (ou microsserviços) em uma única operação lógica.
* `BrowserInfo`: Informações do nome/versão do navegador do usuário atual, se disponível.
* `HttpMethod`: Método HTTP da solicitação atual (GET, POST, PUT, DELETE... etc.).
* `HttpStatusCode`: Código de status da resposta HTTP para esta solicitação.
* `Url`: URL da solicitação.
* **AuditLogActionInfo**: Um log de auditoria de ação é tipicamente uma ação de controlador ou uma chamada de método de [serviço de aplicação](Application-Services.md) durante a solicitação web. Um log de ação pode conter várias ações. Um objeto de ação tem as seguintes propriedades:
* `ServiceName`: Nome do controlador/serviço executado.
* `MethodName`: Nome do método executado do controlador/serviço.
* `Parameters`: Um texto formatado em JSON representando os parâmetros passados para o método.
* `ExecutionTime`: O momento em que este método foi executado.
* `ExecutionDuration`: Duração da execução do método, em milissegundos. Isso pode ser usado para observar o desempenho do método.
* **EntityChangeInfo**: Representa uma alteração de uma entidade nesta solicitação web. Um log de auditoria pode conter zero ou mais alterações de entidade. Uma alteração de entidade tem as seguintes propriedades:
* `ChangeTime`: O momento em que a entidade foi alterada.
* `ChangeType`: Um enum com os seguintes campos: `Criado` (0), `Atualizado` (1) e `Excluído` (2).
* `EntityId`: Id da entidade que foi alterada.
* `EntityTenantId`: Id do locatário a que esta entidade pertence.
* `EntityTypeFullName`: Nome do tipo (classe) da entidade com namespace completo (como *Acme.BookStore.Book* para a entidade Book).
* **EntityPropertyChangeInfo**: Representa uma alteração de uma propriedade de uma entidade. Uma informação de alteração de entidade (explicada acima) pode conter uma ou mais alterações de propriedade com as seguintes propriedades:
* `NewValue`: Novo valor da propriedade. É `null` se a entidade foi excluída.
* `OriginalValue`: Valor antigo/original antes da alteração. É `null` se a entidade foi recém-criada.
* `PropertyName`: O nome da propriedade na classe da entidade.
* `PropertyTypeFullName`: Nome do tipo (classe) da propriedade com namespace completo.
* **Exception**: Um objeto de log de auditoria pode conter zero ou mais exceções. Dessa forma, você pode obter um relatório das solicitações com falha.
* **Comment**: Um valor de string arbitrário para adicionar mensagens personalizadas à entrada de log de auditoria. Um objeto de log de auditoria pode conter zero ou mais comentários.
Além das propriedades padrão explicadas acima, os objetos `AuditLogInfo`, `AuditLogActionInfo` e `EntityChangeInfo` implementam a interface `IHasExtraProperties`, para que você possa adicionar propriedades personalizadas a esses objetos.
## Contribuidores de Log de Auditoria
Você pode estender o sistema de auditoria criando uma classe derivada da classe `AuditLogContributor`, que define os métodos `PreContribute` e `PostContribute`.
O único contribuidor pré-construído é a classe `AspNetCoreAuditLogContributor`, que define as propriedades relacionadas a uma solicitação HTTP.
Um contribuidor pode definir propriedades e coleções da classe `AuditLogInfo` para adicionar mais informações.
Exemplo:
````csharp
public class MyAuditLogContributor : AuditLogContributor
{
public override void PreContribute(AuditLogContributionContext context)
{
var currentUser = context.ServiceProvider.GetRequiredService<ICurrentUser>();
context.AuditInfo.SetProperty(
"MyCustomClaimValue",
currentUser.FindClaimValue("MyCustomClaim")
);
}
public override void PostContribute(AuditLogContributionContext context)
{
context.AuditInfo.Comments.Add("Algum comentário...");
}
}
````
* `context.ServiceProvider` pode ser usado para resolver serviços da [injeção de dependência](Dependency-Injection.md).
* `context.AuditInfo` pode ser usado para acessar o objeto de log de auditoria atual para manipulá-lo.
Após criar um contribuidor, você deve adicioná-lo à lista `AbpAuditingOptions.Contributors`:
````csharp
Configure<AbpAuditingOptions>(options =>
{
options.Contributors.Add(new MyAuditLogContributor());
});
````
## IAuditLogScope & IAuditingManager
Esta seção explica os serviços `IAuditLogScope` e `IAuditingManager` para casos de uso avançados.
Um **escopo de log de auditoria** é um [escopo ambiente](Ambient-Context-Pattern.md) que **constrói** e **salva** um objeto de log de auditoria (explicado anteriormente). Por padrão, um escopo de log de auditoria é criado para uma solicitação web pelo Middleware de Log de Auditoria (veja a seção `UseAuditing()` acima).
### Acesso ao Escopo Atual de Log de Auditoria
Os contribuidores de log de auditoria, explicados acima, são uma maneira global de manipular o objeto de log de auditoria. É bom se você puder obter um valor de um serviço.
Se você precisar manipular o objeto de log de auditoria em um ponto arbitrário de sua aplicação, pode acessar o escopo de log de auditoria atual e obter o objeto de log de auditoria atual (independente de como o escopo é gerenciado). Exemplo:
````csharp
public class MeuServico : ITransientDependency
{
private readonly IAuditingManager _auditingManager;
public MeuServico(IAuditingManager auditingManager)
{
_auditingManager = auditingManager;
}
public async Task FazerIssoAsync()
{
var escopoAtualDeLogDeAuditoria = _auditingManager.Current;
if (escopoAtualDeLogDeAuditoria != null)
{
escopoAtualDeLogDeAuditoria.Log.Comments.Add(
"Executou o método MeuServico.FazerIssoAsync :)"
);
escopoAtualDeLogDeAuditoria.Log.SetProperty("MinhaPropriedadePersonalizada", 42);
}
}
}
````
Sempre verifique se `_auditingManager.Current` é nulo ou não, porque é controlado em um escopo externo e você não pode saber se um escopo de log de auditoria foi criado antes de chamar seu método.
### Criar Manualmente um Escopo de Log de Auditoria
Raramente você precisa criar manualmente um escopo de log de auditoria, mas se precisar, pode criar um escopo de log de auditoria usando o `IAuditingManager` como no exemplo a seguir:
````csharp
public class MeuServico : ITransientDependency
{
private readonly IAuditingManager _auditingManager;
public MeuServico(IAuditingManager auditingManager)
{
_auditingManager = auditingManager;
}
public async Task FazerIssoAsync()
{
using (var escopoDeAuditoria = _auditingManager.BeginScope())
{
try
{
//Chame outros serviços...
}
catch (Exception ex)
{
//Adicione exceções
_auditingManager.Current.Log.Exceptions.Add(ex);
throw;
}
finally
{
//Sempre salve o log
await escopoDeAuditoria.SaveAsync();
}
}
}
}
````
Você pode chamar outros serviços, que podem chamar outros, que podem alterar entidades e assim por diante. Todas essas interações são salvas como um único objeto de log de auditoria no bloco finally.
## O Módulo de Registro de Auditoria
O Módulo de Registro de Auditoria basicamente implementa o `IAuditingStore` para salvar os objetos de log de auditoria em um banco de dados. Ele suporta vários provedores de banco de dados. Este módulo é adicionado aos modelos de inicialização por padrão.
Consulte o documento [Módulo de Registro de Auditoria](Modules/Audit-Logging.md) para mais informações.

360
docs/pt-BR/Authorization.md

@ -1,3 +1,359 @@
## Authorization
# Autorização
Façam
A autorização é usada para verificar se um usuário tem permissão para realizar operações específicas na aplicação.
O ABP estende a [Autorização do ASP.NET Core](https://docs.microsoft.com/pt-br/aspnet/core/security/authorization/introduction) adicionando **permissões** como [políticas](https://docs.microsoft.com/pt-br/aspnet/core/security/authorization/policies) automáticas e permitindo que o sistema de autorização seja utilizado nos **[serviços de aplicação](Application-Services.md)** também.
Portanto, todos os recursos de autorização do ASP.NET Core e a documentação são válidos em uma aplicação baseada no ABP. Este documento se concentra nos recursos adicionados ao sistema de autorização do ASP.NET Core.
## Atributo Authorize
O ASP.NET Core define o atributo [**Authorize**](https://docs.microsoft.com/pt-br/aspnet/core/security/authorization/simple) que pode ser usado para uma ação, um controlador ou uma página. O ABP permite que você use o mesmo atributo para um [serviço de aplicação](Application-Services.md).
Exemplo:
```csharp
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Volo.Abp.Application.Services;
namespace Acme.BookStore
{
[Authorize]
public class AuthorAppService : ApplicationService, IAuthorAppService
{
public Task<List<AuthorDto>> GetListAsync()
{
...
}
[AllowAnonymous]
public Task<AuthorDto> GetAsync(Guid id)
{
...
}
[Authorize("BookStore_Author_Create")]
public Task CreateAsync(CreateAuthorDto input)
{
...
}
}
}
```
- O atributo `Authorize` obriga o usuário a fazer login na aplicação para usar os métodos do `AuthorAppService`. Portanto, o método `GetListAsync` está disponível apenas para usuários autenticados.
- `AllowAnonymous` suprime a autenticação. Portanto, o método `GetAsync` está disponível para todos, incluindo usuários não autorizados.
- `[Authorize("BookStore_Author_Create")]` define uma política (consulte [autorização baseada em políticas](https://docs.microsoft.com/pt-br/aspnet/core/security/authorization/policies)) que é verificada para autorizar o usuário atual.
"BookStore_Author_Create" é um nome de política arbitrário. Se você declarar um atributo como esse, o sistema de autorização do ASP.NET Core espera que uma política seja definida anteriormente.
Você pode, é claro, implementar suas próprias políticas conforme descrito na documentação do ASP.NET Core. Mas para condições simples de verdadeiro/falso, como se uma política foi concedida a um usuário ou não, o ABP define o sistema de permissões, que será explicado na próxima seção.
## Sistema de Permissões
Uma permissão é uma política simples que é concedida ou proibida para um usuário, função ou cliente específico.
### Definindo Permissões
Para definir permissões, crie uma classe que herde de `PermissionDefinitionProvider`, conforme mostrado abaixo:
```csharp
using Volo.Abp.Authorization.Permissions;
namespace Acme.BookStore.Permissions
{
public class BookStorePermissionDefinitionProvider : PermissionDefinitionProvider
{
public override void Define(IPermissionDefinitionContext context)
{
var myGroup = context.AddGroup("BookStore");
myGroup.AddPermission("BookStore_Author_Create");
}
}
}
```
> O ABP descobre automaticamente essa classe. Nenhuma configuração adicional é necessária!
> Normalmente, você define essa classe dentro do projeto `Application.Contracts` da sua [aplicação](Startup-Templates/Application.md). O modelo de inicialização já vem com uma classe vazia chamada *YourProjectNamePermissionDefinitionProvider* com a qual você pode começar.
No método `Define`, você precisa adicionar um **grupo de permissões** ou obter um grupo existente e adicionar **permissões** a esse grupo.
Quando você define uma permissão, ela se torna utilizável no sistema de autorização do ASP.NET Core como um nome de **política**. Ela também se torna visível na interface do usuário. Veja o diálogo de permissões para uma função:
![authorization-new-permission-ui](images/authorization-new-permission-ui.png)
- O grupo "BookStore" é mostrado como uma nova guia no lado esquerdo.
- "BookStore_Author_Create" no lado direito é o nome da permissão. Você pode concedê-la ou proibi-la para a função.
Quando você salva o diálogo, ele é salvo no banco de dados e usado no sistema de autorização.
> A tela acima está disponível quando você instalou o módulo de identidade, que é usado principalmente para gerenciamento de usuários e funções. Os modelos de inicialização já vêm com o módulo de identidade pré-instalado.
#### Localizando o Nome da Permissão
"BookStore_Author_Create" não é um bom nome de permissão para a interface do usuário. Felizmente, os métodos `AddPermission` e `AddGroup` podem receber um `LocalizableString` como segundo parâmetro:
```csharp
var myGroup = context.AddGroup(
"BookStore",
LocalizableString.Create<BookStoreResource>("BookStore")
);
myGroup.AddPermission(
"BookStore_Author_Create",
LocalizableString.Create<BookStoreResource>("Permission:BookStore_Author_Create")
);
```
Em seguida, você pode definir os textos para as chaves "BookStore" e "Permission:BookStore_Author_Create" no arquivo de localização:
```json
"BookStore": "Livraria",
"Permission:BookStore_Author_Create": "Criar um novo autor"
```
> Para mais informações, consulte a [documentação de localização](Localization.md) sobre o sistema de localização.
A interface do usuário localizada será como mostrado abaixo:
![authorization-new-permission-ui-localized](images/authorization-new-permission-ui-localized.png)
#### Multi-Tenancy
O ABP suporta [multi-tenancy](Multi-Tenancy.md) como um recurso de primeira classe. Você pode definir a opção de lado de multi-tenancy ao definir uma nova permissão. Ela pode ter um dos três valores definidos abaixo:
- **Host**: A permissão está disponível apenas para o lado do host.
- **Tenant**: A permissão está disponível apenas para o lado do tenant.
- **Ambos** (padrão): A permissão está disponível tanto para o lado do tenant quanto para o lado do host.
> Se sua aplicação não é multi-tenant, você pode ignorar essa opção.
Para definir a opção de lado de multi-tenancy, passe para o terceiro parâmetro do método `AddPermission`:
```csharp
myGroup.AddPermission(
"BookStore_Author_Create",
LocalizableString.Create<BookStoreResource>("Permission:BookStore_Author_Create"),
multiTenancySide: MultiTenancySides.Tenant //defina o lado de multi-tenancy!
);
```
#### Habilitar/Desabilitar Permissões
Uma permissão está habilitada por padrão. É possível desabilitar uma permissão. Uma permissão desabilitada será proibida para todos. Você ainda pode verificar a permissão, mas ela sempre retornará proibida.
Exemplo de definição:
````csharp
myGroup.AddPermission("Author_Management", isEnabled: false);
````
Normalmente, você não precisa definir uma permissão desabilitada (a menos que queira desabilitar temporariamente um recurso da sua aplicação). No entanto, você pode querer desabilitar uma permissão definida em um módulo dependente. Dessa forma, você pode desabilitar a funcionalidade relacionada à aplicação. Consulte a seção "*Alterando as Definições de Permissão de um Módulo Dependente*" abaixo para um exemplo de uso.
> Observação: Verificar uma permissão não definida lançará uma exceção, enquanto verificar uma permissão desabilitada simplesmente retornará proibida (falso).
#### Permissões Filhas
Uma permissão pode ter permissões filhas. Isso é especialmente útil quando você deseja criar uma árvore de permissões hierárquica, onde uma permissão pode ter permissões secundárias adicionais que estão disponíveis apenas se a permissão pai for concedida.
Exemplo de definição:
```csharp
var authorManagement = myGroup.AddPermission("Author_Management");
authorManagement.AddChild("Author_Management_Create_Books");
authorManagement.AddChild("Author_Management_Edit_Books");
authorManagement.AddChild("Author_Management_Delete_Books");
```
O resultado na interface do usuário é mostrado abaixo (provavelmente você desejará localizar as permissões para sua aplicação):
![authorization-new-permission-ui-hierarcy](images/authorization-new-permission-ui-hierarcy.png)
Para o código de exemplo, é assumido que uma função/usuário com a permissão "Author_Management" concedida pode ter permissões adicionais. Em seguida, um serviço de aplicação típico que verifica permissões pode ser definido como mostrado abaixo:
```csharp
[Authorize("Author_Management")]
public class AuthorAppService : ApplicationService, IAuthorAppService
{
public Task<List<AuthorDto>> GetListAsync()
{
...
}
public Task<AuthorDto> GetAsync(Guid id)
{
...
}
[Authorize("Author_Management_Create_Books")]
public Task CreateAsync(CreateAuthorDto input)
{
...
}
[Authorize("Author_Management_Edit_Books")]
public Task UpdateAsync(CreateAuthorDto input)
{
...
}
[Authorize("Author_Management_Delete_Books")]
public Task DeleteAsync(CreateAuthorDto input)
{
...
}
}
```
- `GetListAsync` e `GetAsync` estarão disponíveis para usuários se a permissão `Author_Management` for concedida.
- Outros métodos requerem permissões adicionais.
### Substituindo uma Permissão por uma Política Personalizada
Se você definir e registrar uma política no sistema de autorização do ASP.NET Core com o mesmo nome de uma permissão, sua política substituirá a permissão existente. Isso é uma maneira poderosa de estender a autorização para um módulo pré-construído que você está usando em sua aplicação.
Consulte o documento [autorização baseada em políticas](https://docs.microsoft.com/pt-br/aspnet/core/security/authorization/policies) para aprender como definir uma política personalizada.
### Alterando as Definições de Permissão de um Módulo Dependente
Uma classe derivada de `PermissionDefinitionProvider` (assim como o exemplo acima) também pode obter definições de permissão existentes (definidas pelos [módulos](Module-Development-Basics.md) dependentes) e alterar suas definições.
Exemplo:
````csharp
context
.GetPermissionOrNull(IdentityPermissions.Roles.Delete)
.IsEnabled = false;
````
Quando você escreve esse código dentro do seu provedor de definição de permissão, ele encontra a permissão de "exclusão de função" do [Módulo de Identidade](Modules/Identity.md) e desabilita a permissão, para que ninguém possa excluir uma função na aplicação.
> Dica: É melhor verificar o valor retornado pelo método `GetPermissionOrNull`, pois ele pode retornar nulo se a permissão fornecida não foi definida.
### Provedores de Valor de Permissão
O sistema de verificação de permissões é extensível. Qualquer classe derivada de `PermissionValueProvider` (ou que implemente `IPermissionValueProvider`) pode contribuir para a verificação de permissões. Existem três provedores de valor predefinidos:
- `UserPermissionValueProvider` verifica se o usuário atual tem a permissão concedida. Ele obtém o ID do usuário das reivindicações atuais. O nome da reivindicação do usuário é definido pela propriedade estática `AbpClaimTypes.UserId`.
- `RolePermissionValueProvider` verifica se algum dos papéis do usuário atual tem a permissão concedida. Ele obtém os nomes dos papéis das reivindicações atuais. O nome das reivindicações de papéis é definido pela propriedade estática `AbpClaimTypes.Role`.
- `ClientPermissionValueProvider` verifica se o cliente atual tem a permissão concedida. Isso é especialmente útil em uma interação máquina a máquina, onde não há usuário atual. Ele obtém o ID do cliente das reivindicações atuais. O nome da reivindicação do cliente é definido pela propriedade estática `AbpClaimTypes.ClientId`.
Você pode estender o sistema de verificação de permissões definindo seu próprio provedor de valor de permissão.
Exemplo:
```csharp
public class SystemAdminPermissionValueProvider : PermissionValueProvider
{
public SystemAdminPermissionValueProvider(IPermissionStore permissionStore)
: base(permissionStore)
{
}
public override string Name => "SystemAdmin";
public async override Task<PermissionGrantResult>
CheckAsync(PermissionValueCheckContext context)
{
if (context.Principal?.FindFirst("User_Type")?.Value == "SystemAdmin")
{
return PermissionGrantResult.Granted;
}
return PermissionGrantResult.Undefined;
}
}
```
Esse provedor permite que todas as permissões sejam concedidas a um usuário com uma reivindicação `User_Type` que tenha o valor `SystemAdmin`. É comum usar as reivindicações atuais e o `IPermissionStore` em um provedor de valor de permissão.
Um provedor de valor de permissão deve retornar um dos seguintes valores do método `CheckAsync`:
- `PermissionGrantResult.Granted` é retornado para conceder a permissão ao usuário. Se qualquer um dos provedores retornar `Granted`, o resultado será `Granted`, se nenhum outro provedor retornar `Prohibited`.
- `PermissionGrantResult.Prohibited` é retornado para proibir a permissão ao usuário. Se qualquer um dos provedores retornar `Prohibited`, o resultado será sempre `Prohibited`. Não importa o que os outros provedores retornem.
- `PermissionGrantResult.Undefined` é retornado se esse provedor de valor de permissão não puder decidir sobre o valor da permissão. Retorne isso para permitir que outros provedores verifiquem a permissão.
Uma vez que um provedor é definido, ele deve ser adicionado às `AbpPermissionOptions`, como mostrado abaixo:
```csharp
Configure<AbpPermissionOptions>(options =>
{
options.ValueProviders.Add<SystemAdminPermissionValueProvider>();
});
```
### Armazenamento de Permissões
`IPermissionStore` é a única interface que precisa ser implementada para ler o valor das permissões de uma fonte de persistência, geralmente um sistema de banco de dados. O módulo de gerenciamento de permissões a implementa e é pré-instalado no modelo de inicialização da aplicação. Consulte a [documentação do módulo de gerenciamento de permissões](Modules/Permission-Management.md) para obter mais informações.
### AlwaysAllowAuthorizationService
`AlwaysAllowAuthorizationService` é uma classe usada para ignorar o serviço de autorização. Geralmente é usado em testes de integração, onde você pode querer desabilitar o sistema de autorização.
Use o método de extensão `IServiceCollection.AddAlwaysAllowAuthorization()` para registrar o `AlwaysAllowAuthorizationService` no sistema de [injeção de dependência](Dependency-Injection.md):
```csharp
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddAlwaysAllowAuthorization();
}
```
Isso já é feito para testes de integração do modelo de inicialização.
### Fábrica de Claims Principal
As reivindicações são elementos importantes da autenticação e autorização. O ABP usa o serviço `IAbpClaimsPrincipalFactory` para criar reivindicações na autenticação. Esse serviço foi projetado para ser extensível. Se você precisar adicionar suas próprias reivindicações ao ticket de autenticação, poderá implementar `IAbpClaimsPrincipalContributor` em sua aplicação.
**Exemplo: Adicionar uma reivindicação `SocialSecurityNumber` e obtê-la:**
```csharp
public class SocialSecurityNumberClaimsPrincipalContributor : IAbpClaimsPrincipalContributor, ITransientDependency
{
public async Task ContributeAsync(AbpClaimsPrincipalContributorContext context)
{
var identity = context.ClaimsPrincipal.Identities.FirstOrDefault();
var userId = identity?.FindUserId();
if (userId.HasValue)
{
var userService = context.ServiceProvider.GetRequiredService<IUserService>(); //Seu serviço personalizado
var socialSecurityNumber = await userService.GetSocialSecurityNumberAsync(userId.Value);
if (socialSecurityNumber != null)
{
identity.AddClaim(new Claim("SocialSecurityNumber", socialSecurityNumber));
}
}
}
}
public static class CurrentUserExtensions
{
public static string GetSocialSecurityNumber(this ICurrentUser currentUser)
{
return currentUser.FindClaimValue("SocialSecurityNumber");
}
}
```
> Se você estiver usando o Identity Server, adicione suas reivindicações a `RequestedClaims` de `AbpClaimsServiceOptions`.
```csharp
Configure<AbpClaimsServiceOptions>(options =>
{
options.RequestedClaims.AddRange(new[]{ "SocialSecurityNumber" });
});
```
## Veja também
* [Módulo de Gerenciamento de Permissões](Modules/Permission-Management.md)
* [API de Autenticação JavaScript do ASP.NET Core MVC / Razor Pages](UI/AspNetCore/JavaScript-API/Auth.md)
* [Gerenciamento de Permissões na Interface do Usuário Angular](UI/Angular/Permission-Management.md)
* [Tutorial em vídeo](https://abp.io/video-courses/essentials/authorization)</source>

159
docs/pt-BR/Background-Jobs-Quartz.md

@ -0,0 +1,159 @@
# Gerenciador de Tarefas em Segundo Plano Quartz
[Quartz](https://www.quartz-scheduler.net/) é um avançado gerenciador de tarefas em segundo plano. Você pode integrar o Quartz com o ABP Framework para usá-lo em vez do [gerenciador de tarefas em segundo plano padrão](Background-Jobs.md). Dessa forma, você pode usar a mesma API de tarefas em segundo plano para o Quartz e seu código será independente do Quartz. Se preferir, você também pode usar diretamente a API do Quartz.
> Consulte o [documento de tarefas em segundo plano](Background-Jobs.md) para aprender como usar o sistema de tarefas em segundo plano. Este documento mostra apenas como instalar e configurar a integração com o Quartz.
## Instalação
É sugerido usar o [ABP CLI](CLI.md) para instalar este pacote.
### Usando o ABP CLI
Abra uma janela de linha de comando na pasta do projeto (arquivo .csproj) e digite o seguinte comando:
````bash
abp add-package Volo.Abp.BackgroundJobs.Quartz
````
> Se você ainda não o fez, primeiro precisa instalar o [ABP CLI](CLI.md). Para outras opções de instalação, consulte [a página de descrição do pacote](https://abp.io/package-detail/Volo.Abp.BackgroundJobs.Quartz).
### Instalação Manual
Se você deseja instalar manualmente:
1. Adicione o pacote NuGet [Volo.Abp.BackgroundJobs.Quartz](https://www.nuget.org/packages/Volo.Abp.BackgroundJobs.Quartz) ao seu projeto:
````
Install-Package Volo.Abp.BackgroundJobs.Quartz
````
2. Adicione o `AbpBackgroundJobsQuartzModule` à lista de dependências do seu módulo:
````csharp
[DependsOn(
//...outras dependências
typeof(AbpBackgroundJobsQuartzModule) //Adicione a nova dependência do módulo
)]
public class SeuModulo : AbpModule
{
}
````
## Configuração
O Quartz é uma biblioteca muito configurável e o framework ABP fornece `AbpQuartzOptions` para isso. Você pode usar o método `PreConfigure` na classe do seu módulo para pré-configurar essa opção. O ABP a usará ao inicializar o módulo Quartz. Por exemplo:
````csharp
[DependsOn(
//...outras dependências
typeof(AbpBackgroundJobsQuartzModule) //Adicione a nova dependência do módulo
)]
public class SeuModulo : AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
PreConfigure<AbpQuartzOptions>(options =>
{
options.Properties = new NameValueCollection
{
["quartz.jobStore.dataSource"] = "BackgroundJobsDemoApp",
["quartz.jobStore.type"] = "Quartz.Impl.AdoJobStore.JobStoreTX, Quartz",
["quartz.jobStore.tablePrefix"] = "QRTZ_",
["quartz.serializer.type"] = "json",
["quartz.dataSource.BackgroundJobsDemoApp.connectionString"] = configuration.GetConnectionString("Quartz"),
["quartz.dataSource.BackgroundJobsDemoApp.provider"] = "SqlServer",
["quartz.jobStore.driverDelegateType"] = "Quartz.Impl.AdoJobStore.SqlServerDelegate, Quartz",
};
});
}
}
````
A partir da versão 3.1 do ABP, adicionamos o `Configurator` ao `AbpQuartzOptions` para configurar o Quartz. Por exemplo:
````csharp
[DependsOn(
//...outras dependências
typeof(AbpBackgroundJobsQuartzModule) //Adicione a nova dependência do módulo
)]
public class SeuModulo : AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
PreConfigure<AbpQuartzOptions>(options =>
{
options.Configurator = configure =>
{
configure.UsePersistentStore(storeOptions =>
{
storeOptions.UseProperties = true;
storeOptions.UseJsonSerializer();
storeOptions.UseSqlServer(configuration.GetConnectionString("Quartz"));
storeOptions.UseClustering(c =>
{
c.CheckinMisfireThreshold = TimeSpan.FromSeconds(20);
c.CheckinInterval = TimeSpan.FromSeconds(10);
});
});
};
});
}
}
````
> Você pode escolher a maneira que preferir para configurar o Quartz.
O Quartz armazena informações de tarefas e agendamento **em memória por padrão**. No exemplo, usamos a pré-configuração do [padrão de opções](Options.md) para alterá-lo para o banco de dados. Para mais configurações do Quartz, consulte a [documentação do Quartz](https://www.quartz-scheduler.net/).
## Tratamento de Exceções
### Estratégia de tratamento de exceções padrão
Quando ocorre uma exceção na tarefa em segundo plano, o ABP fornece a **estratégia de tratamento padrão** que tenta novamente a cada 3 segundos, até 3 vezes. Você pode alterar a contagem de tentativas e o intervalo de tentativa por meio das opções `AbpBackgroundJobQuartzOptions`:
```csharp
[DependsOn(
//...outras dependências
typeof(AbpBackgroundJobsQuartzModule) //Adicione a nova dependência do módulo
)]
public class SeuModulo : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpBackgroundJobQuartzOptions>(options =>
{
options.RetryCount = 1;
options.RetryIntervalMillisecond = 1000;
});
}
}
```
### Personalizar a estratégia de tratamento de exceções
Você pode personalizar a estratégia de tratamento de exceções por meio das opções `AbpBackgroundJobQuartzOptions`:
```csharp
[DependsOn(
//...outras dependências
typeof(AbpBackgroundJobsQuartzModule) //Adicione a nova dependência do módulo
)]
public class SeuModulo : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpBackgroundJobQuartzOptions>(options =>
{
options.RetryStrategy = async (retryIndex, executionContext, exception) =>
{
// personalizar o tratamento de exceções
};
});
}
}
```</source>

146
docs/pt-BR/Background-Workers-Quartz.md

@ -0,0 +1,146 @@
# Gerenciador de Trabalhadores em Segundo Plano Quartz
[Quartz](https://www.quartz-scheduler.net/) é um avançado gerenciador de trabalhadores em segundo plano. Você pode integrar o Quartz com o ABP Framework para usá-lo em vez do [gerenciador de trabalhadores em segundo plano padrão](Background-Workers.md). O ABP simplesmente integra o Quartz.
## Instalação
É sugerido usar o [ABP CLI](CLI.md) para instalar este pacote.
### Usando o ABP CLI
Abra uma janela de linha de comando na pasta do projeto (arquivo .csproj) e digite o seguinte comando:
````bash
abp add-package Volo.Abp.BackgroundWorkers.Quartz
````
### Instalação Manual
Se você deseja instalar manualmente:
1. Adicione o pacote NuGet [Volo.Abp.BackgroundWorkers.Quartz](https://www.nuget.org/packages/Volo.Abp.BackgroundWorkers.Quartz) ao seu projeto:
````
Install-Package Volo.Abp.BackgroundWorkers.Quartz
````
2. Adicione o módulo `AbpBackgroundWorkersQuartzModule` à lista de dependências do seu módulo:
````csharp
[DependsOn(
//...outras dependências
typeof(AbpBackgroundWorkersQuartzModule) //Adicione a nova dependência do módulo
)]
public class SeuModulo : AbpModule
{
}
````
> A integração do trabalhador em segundo plano do Quartz fornece o adaptador `QuartzPeriodicBackgroundWorkerAdapter` para adaptar as classes derivadas `PeriodicBackgroundWorkerBase` e `AsyncPeriodicBackgroundWorkerBase`. Portanto, você ainda pode seguir o [documento de trabalhadores em segundo plano](Background-Workers.md) para definir o trabalhador em segundo plano.
## Configuração
Veja [Configuração](Background-Jobs-Quartz#Configuração).
## Criar um Trabalhador em Segundo Plano
Um trabalho em segundo plano é uma classe que deriva da classe base `QuartzBackgroundWorkerBase`. Por exemplo, uma classe de trabalhador simples é mostrada abaixo:
```` csharp
public class MeuTrabalhadorDeLog : QuartzBackgroundWorkerBase
{
public MeuTrabalhadorDeLog()
{
JobDetail = JobBuilder.Create<MeuTrabalhadorDeLog>().WithIdentity(nameof(MeuTrabalhadorDeLog)).Build();
Trigger = TriggerBuilder.Create().WithIdentity(nameof(MeuTrabalhadorDeLog)).StartNow().Build();
}
public override Task Execute(IJobExecutionContext context)
{
Logger.LogInformation("Executando MeuTrabalhadorDeLog..!");
return Task.CompletedTask;
}
}
````
Nós simplesmente implementamos o método Execute para escrever um log. O trabalhador em segundo plano é um **singleton por padrão**. Se desejar, você também pode implementar uma [interface de dependência](Dependency-Injection#Interfaces-de-Dependência) para registrá-lo com outro ciclo de vida.
> Dica: Adicionar identidade aos trabalhadores em segundo plano é uma boa prática, pois o Quartz distingue trabalhos diferentes com base na identidade.
## Adicionar ao BackgroundWorkerManager
Os trabalhadores em segundo plano padrão são **adicionados automaticamente** ao BackgroundWorkerManager quando a aplicação é **inicializada**. Você pode definir o valor da propriedade `AutoRegister` como `false`, se desejar adicioná-lo manualmente:
```` csharp
public class MeuTrabalhadorDeLog : QuartzBackgroundWorkerBase
{
public MeuTrabalhadorDeLog()
{
AutoRegister = false;
JobDetail = JobBuilder.Create<MeuTrabalhadorDeLog>().WithIdentity(nameof(MeuTrabalhadorDeLog)).Build();
Trigger = TriggerBuilder.Create().WithIdentity(nameof(MeuTrabalhadorDeLog)).StartNow().Build();
}
public override Task Execute(IJobExecutionContext context)
{
Logger.LogInformation("Executando MeuTrabalhadorDeLog..!");
return Task.CompletedTask;
}
}
````
Se você deseja desabilitar globalmente a adição automática de trabalhadores, você pode desabilitá-la globalmente através das opções `AbpBackgroundWorkerQuartzOptions`:
```csharp
[DependsOn(
//...outras dependências
typeof(AbpBackgroundWorkersQuartzModule) //Adicione a nova dependência do módulo
)]
public class SeuModulo : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpBackgroundWorkerQuartzOptions>(options =>
{
options.IsAutoRegisterEnabled = false;
});
}
}
```
## Tópicos Avançados
### Personalizar o ScheduleJob
Suponha que você tenha um trabalhador que é executado a cada 10 minutos, mas devido a um servidor indisponível por 30 minutos, 3 execuções são perdidas. Você deseja executar todas as execuções perdidas quando o servidor estiver disponível novamente. Você deve definir seu trabalhador em segundo plano da seguinte forma:
```csharp
public class MeuTrabalhadorDeLog : QuartzBackgroundWorkerBase
{
public MeuTrabalhadorDeLog()
{
JobDetail = JobBuilder.Create<MeuTrabalhadorDeLog>().WithIdentity(nameof(MeuTrabalhadorDeLog)).Build();
Trigger = TriggerBuilder.Create().WithIdentity(nameof(MeuTrabalhadorDeLog)).WithSimpleSchedule(s=>s.WithIntervalInMinutes(1).RepeatForever().WithMisfireHandlingInstructionIgnoreMisfires()).Build();
ScheduleJob = async scheduler =>
{
if (!await scheduler.CheckExists(JobDetail.Key))
{
await scheduler.ScheduleJob(JobDetail, Trigger);
}
};
}
public override Task Execute(IJobExecutionContext context)
{
Logger.LogInformation("Executando MeuTrabalhadorDeLog..!");
return Task.CompletedTask;
}
}
```
No exemplo, definimos o intervalo de execução do trabalhador como 10 minutos e definimos `WithMisfireHandlingInstructionIgnoreMisfires`. Personalizamos o `ScheduleJob` e adicionamos o trabalhador ao Quartz somente quando o trabalhador em segundo plano não existe.
### Mais
Consulte a [documentação](https://www.quartz-scheduler.net/documentation/index.html) do Quartz para obter mais informações.

144
docs/pt-BR/Background-Workers.md

@ -0,0 +1,144 @@
# Background Workers
## Introdução
Background workers são threads independentes simples na aplicação que são executadas em segundo plano. Geralmente, eles são executados periodicamente para realizar algumas tarefas. Exemplos:
* Um background worker pode ser executado periodicamente para **excluir logs antigos**.
* Um background worker pode ser executado periodicamente para **identificar usuários inativos** e **enviar e-mails** para fazer com que os usuários retornem à sua aplicação.
## Criando um Background Worker
Um background worker deve implementar diretamente ou indiretamente a interface `IBackgroundWorker`.
> Um background worker é inerentemente [singleton](Dependency-Injection.md). Portanto, apenas uma única instância da sua classe de worker é instanciada e executada.
### BackgroundWorkerBase
`BackgroundWorkerBase` é uma maneira fácil de criar um background worker.
````csharp
public class MyWorker : BackgroundWorkerBase
{
public override Task StartAsync(CancellationToken cancellationToken = default)
{
//...
}
public override Task StopAsync(CancellationToken cancellationToken = default)
{
//...
}
}
````
Inicie o seu worker no método `StartAsync` (que é chamado quando a aplicação é iniciada) e pare no método `StopAsync` (que é chamado quando a aplicação é encerrada).
> Você pode implementar diretamente a interface `IBackgroundWorker`, mas `BackgroundWorkerBase` fornece algumas propriedades úteis, como `Logger`.
### AsyncPeriodicBackgroundWorkerBase
Vamos supor que queremos tornar um usuário inativo se ele não tiver feito login na aplicação nos últimos 30 dias. A classe `AsyncPeriodicBackgroundWorkerBase` simplifica a criação de workers periódicos, então vamos usá-la no exemplo abaixo:
````csharp
public class PassiveUserCheckerWorker : AsyncPeriodicBackgroundWorkerBase
{
public PassiveUserCheckerWorker(
AbpAsyncTimer timer,
IServiceScopeFactory serviceScopeFactory
) : base(
timer,
serviceScopeFactory)
{
Timer.Period = 600000; //10 minutos
}
protected async override Task DoWorkAsync(
PeriodicBackgroundWorkerContext workerContext)
{
Logger.LogInformation("Iniciando: Definindo status de usuários inativos...");
//Resolver dependências
var userRepository = workerContext
.ServiceProvider
.GetRequiredService<IUserRepository>();
//Realizar o trabalho
await userRepository.UpdateInactiveUserStatusesAsync();
Logger.LogInformation("Concluído: Definindo status de usuários inativos...");
}
}
````
* `AsyncPeriodicBackgroundWorkerBase` usa o objeto `AbpAsyncTimer` (um timer thread-safe) para determinar **o período**. Podemos definir a propriedade `Period` no construtor.
* É necessário implementar o método `DoWorkAsync` para **executar** o trabalho periódico.
* É uma boa prática **resolver as dependências** a partir do `PeriodicBackgroundWorkerContext` em vez de usar injeção de dependência no construtor. Isso ocorre porque `AsyncPeriodicBackgroundWorkerBase` usa um `IServiceScope` que é **descartado** quando o trabalho é concluído.
* `AsyncPeriodicBackgroundWorkerBase` **captura e registra exceções** lançadas pelo método `DoWorkAsync`.
## Registrando o Background Worker
Após criar a classe do background worker, você deve adicioná-la ao `IBackgroundWorkerManager`. O local mais comum é o método `OnApplicationInitializationAsync` da sua classe de módulo:
````csharp
[DependsOn(typeof(AbpBackgroundWorkersModule))]
public class MyModule : AbpModule
{
public override async Task OnApplicationInitializationAsync(
ApplicationInitializationContext context)
{
await context.AddBackgroundWorkerAsync<PassiveUserCheckerWorker>();
}
}
````
`context.AddBackgroundWorkerAsync(...)` é um método de extensão que simplifica a expressão abaixo:
````csharp
await context.ServiceProvider
.GetRequiredService<IBackgroundWorkerManager>()
.AddAsync(
context
.ServiceProvider
.GetRequiredService<PassiveUserCheckerWorker>()
);
````
Dessa forma, ele resolve o background worker fornecido e o adiciona ao `IBackgroundWorkerManager`.
Embora geralmente adicionemos workers no método `OnApplicationInitializationAsync`, não há restrições quanto a isso. Você pode injetar o `IBackgroundWorkerManager` em qualquer lugar e adicionar workers em tempo de execução. O gerenciador de background workers irá parar e liberar todos os workers registrados quando a aplicação for encerrada.
## Opções
A classe `AbpBackgroundWorkerOptions` é usada para [definir opções](Options.md) para os background workers. Atualmente, há apenas uma opção:
* `IsEnabled` (padrão: true): Usado para **habilitar/desabilitar** o sistema de background workers para a sua aplicação.
> Consulte o documento [Options](Options.md) para aprender como definir opções.
## Mantendo a Aplicação Sempre em Execução
Os background workers só funcionam se a sua aplicação estiver em execução. Se você hospedar a execução do job em segundo plano na sua aplicação web (esse é o comportamento padrão), você deve garantir que a sua aplicação web esteja configurada para sempre estar em execução. Caso contrário, os jobs em segundo plano só funcionarão enquanto a sua aplicação estiver em uso.
## Executando em um Cluster
Tenha cuidado se você executar várias instâncias da sua aplicação simultaneamente em um ambiente de cluster. Nesse caso, cada aplicação executa o mesmo worker, o que pode criar conflitos se os workers estiverem executando em recursos compartilhados (processando os mesmos dados, por exemplo).
Se isso for um problema para os seus workers, você tem as seguintes opções:
* Implemente os seus background workers de forma que eles funcionem em um ambiente de cluster sem problemas. Usar o [lock distribuído](Distributed-Locking.md) para garantir o controle de concorrência é uma forma de fazer isso. Um background worker em uma instância da aplicação pode manipular um lock distribuído, então os workers em outras instâncias da aplicação aguardarão pelo lock. Dessa forma, apenas um worker realiza o trabalho real, enquanto os outros esperam ociosos. Se você implementar isso, os seus workers serão executados com segurança, independentemente de como a aplicação estiver implantada.
* Pare os background workers (defina `AbpBackgroundWorkerOptions.IsEnabled` como `false`) em todas as instâncias da aplicação, exceto em uma delas, para que apenas a instância única execute os workers.
* Pare os background workers (defina `AbpBackgroundWorkerOptions.IsEnabled` como `false`) em todas as instâncias da aplicação e crie uma aplicação dedicada (talvez uma aplicação console executando em seu próprio contêiner ou um serviço do Windows em execução em segundo plano) para executar todas as tarefas em segundo plano. Essa pode ser uma boa opção se os seus background workers consumirem muitos recursos do sistema (CPU, RAM ou Disco), para que você possa implantar essa aplicação de background em um servidor dedicado e suas tarefas em segundo plano não afetem o desempenho da sua aplicação.
## Integrações
O sistema de background workers é extensível e você pode alterar o gerenciador de background workers padrão com a sua própria implementação ou com uma das integrações pré-construídas.
Veja as alternativas de gerenciador de workers pré-construídas:
* [Quartz Background Worker Manager](Background-Workers-Quartz.md)
* [Hangfire Background Worker Manager](Background-Workers-Hangfire.md)
## Veja Também
* [Background Jobs](Background-Jobs.md)

343
docs/pt-BR/Exception-Handling.md

@ -0,0 +1,343 @@
# Tratamento de Exceções
O ABP fornece uma infraestrutura integrada e oferece um modelo padrão para lidar com exceções.
* **Lida automaticamente com todas as exceções** e envia uma **mensagem de erro formatada padrão** para o cliente em uma solicitação de API/AJAX.
* Oculta automaticamente os **erros internos de infraestrutura** e retorna uma mensagem de erro padrão.
* Fornece uma maneira fácil e configurável de **localizar** mensagens de exceção.
* Mapeia automaticamente exceções padrão para **códigos de status HTTP** e fornece uma opção configurável para mapear exceções personalizadas.
## Tratamento Automático de Exceções
O `AbpExceptionFilter` lida com uma exceção se **qualquer uma das seguintes condições** forem atendidas:
* A exceção é lançada por uma **ação do controlador** que retorna um **resultado de objeto** (não um resultado de visualização).
* A solicitação é uma solicitação AJAX (o valor do cabeçalho HTTP `X-Requested-With` é `XMLHttpRequest`).
* O cliente aceita explicitamente o tipo de conteúdo `application/json` (por meio do cabeçalho HTTP `accept`).
Se a exceção for tratada, ela é automaticamente **registrada** e uma **mensagem JSON formatada** é retornada ao cliente.
### Formato da Mensagem de Erro
A mensagem de erro é uma instância da classe `RemoteServiceErrorResponse`. O JSON de erro mais simples tem uma propriedade **message** conforme mostrado abaixo:
````json
{
"error": {
"message": "Este tópico está bloqueado e não é possível adicionar uma nova mensagem"
}
}
````
Existem **campos opcionais** que podem ser preenchidos com base na exceção que ocorreu.
##### Código de Erro
O **código de erro** é um valor de string opcional e único para a exceção. A exceção lançada deve implementar a interface `IHasErrorCode` para preencher este campo. Exemplo de valor JSON:
````json
{
"error": {
"code": "App:010042",
"message": "Este tópico está bloqueado e não é possível adicionar uma nova mensagem"
}
}
````
O código de erro também pode ser usado para localizar a exceção e personalizar o código de status HTTP (consulte as seções relacionadas abaixo).
##### Detalhes do Erro
Os **detalhes do erro** são um campo opcional da mensagem de erro JSON. A exceção lançada deve implementar a interface `IHasErrorDetails` para preencher este campo. Exemplo de valor JSON:
```json
{
"error": {
"code": "App:010042",
"message": "Este tópico está bloqueado e não é possível adicionar uma nova mensagem",
"details": "Informações mais detalhadas sobre o erro..."
}
}
```
##### Erros de Validação
**validationErrors** é um campo padrão que é preenchido se a exceção lançada implementar a interface `IHasValidationErrors`.
````json
{
"error": {
"code": "App:010046",
"message": "Sua solicitação não é válida, corrija e tente novamente!",
"validationErrors": [{
"message": "O nome de usuário deve ter no mínimo 3 caracteres.",
"members": ["userName"]
},
{
"message": "A senha é obrigatória",
"members": ["password"]
}]
}
}
````
`AbpValidationException` implementa a interface `IHasValidationErrors` e é automaticamente lançada pelo framework quando a entrada de uma solicitação não é válida. Portanto, geralmente você não precisa lidar com erros de validação, a menos que tenha lógica de validação altamente personalizada.
### Registro
As exceções capturadas são automaticamente registradas.
#### Nível de Registro
As exceções são registradas com o nível `Error` por padrão. O nível de log pode ser determinado pela exceção se ela implementar a interface `IHasLogLevel`. Exemplo:
````C#
public class MinhaExcecao : Exception, IHasLogLevel
{
public LogLevel LogLevel { get; set; } = LogLevel.Warning;
//...
}
````
#### Exceções de Registro Próprio
Alguns tipos de exceção podem precisar escrever logs adicionais. Eles podem implementar a interface `IExceptionWithSelfLogging` se necessário. Exemplo:
````C#
public class MinhaExcecao : Exception, IExceptionWithSelfLogging
{
public void Log(ILogger logger)
{
//...log informações adicionais
}
}
````
> Os métodos de extensão `ILogger.LogException` são usados para escrever logs de exceção. Você pode usar o mesmo método de extensão quando necessário.
## Exceções de Negócios
A maioria de suas próprias exceções será exceções de negócios. A interface `IBusinessException` é usada para marcar uma exceção como uma exceção de negócios.
`BusinessException` implementa a interface `IBusinessException` além das interfaces `IHasErrorCode`, `IHasErrorDetails` e `IHasLogLevel`. O nível de log padrão é `Warning`.
Normalmente, você tem um código de erro relacionado a uma exceção de negócios específica. Por exemplo:
````C#
throw new BusinessException(QaErrorCodes.CanNotVoteYourOwnAnswer);
````
`QaErrorCodes.CanNotVoteYourOwnAnswer` é apenas uma `const string`. O seguinte formato de código de erro é recomendado:
````
<namespace-do-código>:<código-de-erro>
````
**namespace-do-código** é um **valor único** específico para o seu módulo/aplicação. Exemplo:
````
Volo.Qa:010002
````
`Volo.Qa` é o namespace do código aqui. O namespace do código será então usado ao **localizar** mensagens de exceção.
* Você pode **lançar diretamente** uma `BusinessException` ou **derivar** seus próprios tipos de exceção dela quando necessário.
* Todas as propriedades são opcionais para a classe `BusinessException`. Mas geralmente você define a propriedade `ErrorCode` ou `Message`.
## Localização de Exceções
Um problema ao lançar exceções é como localizar mensagens de erro ao enviá-las para o cliente. O ABP oferece dois modelos e suas variantes.
### Exceção Amigável ao Usuário
Se uma exceção implementa a interface `IUserFriendlyException`, então o ABP não altera suas propriedades `Message` e `Details` e a envia diretamente para o cliente.
A classe `UserFriendlyException` é a implementação integrada da interface `IUserFriendlyException`. Exemplo de uso:
````C#
throw new UserFriendlyException(
"O nome de usuário deve ser único!"
);
````
Dessa forma, **não há necessidade de localização**. Se você deseja localizar a mensagem, pode injetar e usar o **localizador de strings padrão** (consulte o [documento de localização](Localization.md)). Exemplo:
````C#
throw new UserFriendlyException(_stringLocalizer["UserNameShouldBeUniqueMessage"]);
````
Em seguida, defina no **recurso de localização** para cada idioma. Exemplo:
````json
{
"culture": "pt",
"texts": {
"UserNameShouldBeUniqueMessage": "O nome de usuário deve ser único!"
}
}
````
O localizador de strings já suporta **mensagens parametrizadas**. Por exemplo:
````C#
throw new UserFriendlyException(_stringLocalizer["UserNameShouldBeUniqueMessage", "john"]);
````
Em seguida, o texto de localização pode ser:
````json
"UserNameShouldBeUniqueMessage": "O nome de usuário deve ser único! '{0}' já está em uso!"
````
* A interface `IUserFriendlyException` é derivada da `IBusinessException` e a classe `UserFriendlyException` é derivada da classe `BusinessException`.
### Usando Códigos de Erro
`UserFriendlyException` é bom, mas tem alguns problemas em usos avançados:
* Requer que você **injete o localizador de strings** em todos os lugares e sempre o use ao lançar exceções.
* No entanto, em alguns casos, pode **não ser possível** injetar o localizador de strings (em um contexto estático ou em um método de entidade).
Em vez de localizar a mensagem ao lançar a exceção, você pode separar o processo usando **códigos de erro**.
Primeiro, defina o mapeamento do **namespace-do-código** para o **recurso de localização** na configuração do módulo:
````C#
services.Configure<AbpExceptionLocalizationOptions>(options =>
{
options.MapCodeNamespace("Volo.Qa", typeof(QaResource));
});
````
Então, qualquer uma das exceções com o namespace `Volo.Qa` será localizada usando seu recurso de localização fornecido. O recurso de localização deve sempre ter uma entrada com a chave do código de erro. Exemplo:
````json
{
"culture": "pt",
"texts": {
"Volo.Qa:010002": "Você não pode votar em sua própria resposta!"
}
}
````
Então uma exceção de negócios pode ser lançada com o código de erro:
````C#
throw new BusinessException(QaDomainErrorCodes.CanNotVoteYourOwnAnswer);
````
* Lançar qualquer exceção que implemente a interface `IHasErrorCode` se comporta da mesma maneira. Portanto, a abordagem de localização de código de erro não é exclusiva para a classe `BusinessException`.
* Não é necessário definir uma string localizada para uma mensagem de erro. Se não estiver definido, o ABP envia a mensagem de erro padrão para o cliente. Ele não usa a propriedade `Message` da exceção! se você deseja isso, use a `UserFriendlyException` (ou use um tipo de exceção que implemente a interface `IUserFriendlyException`).
#### Usando Parâmetros de Mensagem
Se você tiver uma mensagem de erro parametrizada, poderá defini-la com a propriedade `Data` da exceção. Por exemplo:
````C#
throw new BusinessException("App:010046")
{
Data =
{
{"UserName", "john"}
}
};
````
Felizmente, há uma maneira mais simples de codificar isso:
````C#
throw new BusinessException("App:010046")
.WithData("UserName", "john");
````
Em seguida, o texto localizado pode conter o parâmetro `UserName`:
````json
{
"culture": "pt",
"texts": {
"App:010046": "O nome de usuário deve ser único. '{UserName}' já está em uso!"
}
}
````
* `WithData` pode ser encadeado com mais de um parâmetro (como `.WithData(...).WithData(...)`).
## Mapeamento de Códigos de Status HTTP
O ABP tenta determinar automaticamente o código de status HTTP mais adequado para tipos comuns de exceção seguindo estas regras:
* Para a `AbpAuthorizationException`:
* Retorna `401` (não autorizado) se o usuário não estiver logado.
* Retorna `403` (proibido) se o usuário estiver logado.
* Retorna `400` (requisição inválida) para a `AbpValidationException`.
* Retorna `404` (não encontrado) para a `EntityNotFoundException`.
* Retorna `403` (proibido) para a `IBusinessException` (e `IUserFriendlyException` já que estende a `IBusinessException`).
* Retorna `501` (não implementado) para a `NotImplementedException`.
* Retorna `500` (erro interno do servidor) para outras exceções (que são assumidas como exceções de infraestrutura).
O `IHttpExceptionStatusCodeFinder` é usado para determinar automaticamente o código de status HTTP. A implementação padrão é a classe `DefaultHttpExceptionStatusCodeFinder`. Pode ser substituída ou estendida conforme necessário.
### Mapeamentos Personalizados
A determinação automática do código de status HTTP pode ser substituída por mapeamentos personalizados. Por exemplo:
````C#
services.Configure<AbpExceptionHttpStatusCodeOptions>(options =>
{
options.Map("Volo.Qa:010002", HttpStatusCode.Conflict);
});
````
## Inscrevendo-se nas Exceções
É possível ser informado quando o Framework ABP **manipula uma exceção**. Ele registra automaticamente todas as exceções no [logger padrão](Logging.md), mas você pode querer fazer mais.
Nesse caso, crie uma classe derivada da classe `ExceptionSubscriber` em sua aplicação:
````csharp
public class MeuAssinanteDeExcecao : ExceptionSubscriber
{
public async override Task HandleAsync(ExceptionNotificationContext context)
{
//TODO...
}
}
````
O objeto `context` contém informações necessárias sobre a exceção ocorrida.
> Você pode ter vários assinantes, cada um recebe uma cópia da exceção. As exceções lançadas pelo seu assinante são ignoradas (mas ainda registradas).
## Exceções Integradas
Alguns tipos de exceção são automaticamente lançados pelo framework:
- `AbpAuthorizationException` é lançada se o usuário atual não tiver permissão para realizar a operação solicitada. Consulte [autorização](Authorization.md) para mais informações.
- `AbpValidationException` é lançada se a entrada da solicitação atual não for válida. Consulte [validação](Validation.md) para mais informações.
- `EntityNotFoundException` é lançada se a entidade solicitada não estiver disponível. Isso é lançado principalmente por [repositórios](Repositories.md).
Você também pode lançar esses tipos de exceção em seu código (embora raramente seja necessário).
## AbpExceptionHandlingOptions
`AbpExceptionHandlingOptions` é o principal [objeto de opções](Options.md) para configurar o sistema de tratamento de exceções. Você pode configurá-lo no método `ConfigureServices` do seu [módulo](Module-Development-Basics.md):
````csharp
Configure<AbpExceptionHandlingOptions>(options =>
{
options.SendExceptionsDetailsToClients = true;
options.SendStackTraceToClients = false;
});
````
Aqui está uma lista das opções que você pode configurar:
* `SendExceptionsDetailsToClients` (padrão: `false`): Você pode habilitar ou desabilitar o envio de detalhes da exceção para o cliente.
* `SendStackTraceToClients` (padrão: `true`): Você pode habilitar ou desabilitar o envio da pilha de chamadas da exceção para o cliente. Se você deseja enviar a pilha de chamadas para o cliente, deve definir tanto as opções `SendStackTraceToClients` quanto `SendExceptionsDetailsToClients` como `true`, caso contrário, a pilha de chamadas não será enviada para o cliente.
## Veja Também
* [Tutorial em vídeo](https://abp.io/video-courses/essentials/exception-handling)

80
docs/pt-BR/Modules/Account.md

@ -0,0 +1,80 @@
# Módulo de Conta
O módulo de conta implementa recursos básicos de autenticação, como **login**, **registro**, **recuperação de senha** e **gerenciamento de conta**.
Este módulo é baseado na biblioteca de identidade da Microsoft e no módulo de identidade. Ele possui integração com o IdentityServer (com base no módulo IdentityServer) e com o OpenIddict (com base no módulo OpenIddict) para fornecer autenticação avançada, controle de acesso e outros recursos avançados de autenticação.
## Como instalar
Este módulo já vem pré-instalado (como pacotes NuGet/NPM). Você pode continuar a usá-lo como pacote e obter atualizações facilmente, ou pode incluir seu código-fonte em sua solução (consulte o comando `get-source` da CLI) para desenvolver seu próprio módulo personalizado.
### O código-fonte
O código-fonte deste módulo pode ser acessado [aqui](https://github.com/abpframework/abp/tree/dev/modules/account). O código-fonte está licenciado sob a licença MIT, portanto, você pode usá-lo e personalizá-lo livremente.
## Interface do usuário
Esta seção apresenta as principais páginas fornecidas por este módulo.
### Login
A página `/Account/Login` fornece a funcionalidade de login.
![account-module-login](../images/account-module-login.png)
Os botões de login social/externo ficam visíveis se você configurá-los. Consulte a seção *Logins Sociais/Externos* abaixo. Os links de registro e recuperação de senha redirecionam para as páginas explicadas nas próximas seções.
### Registro
A página `/Account/Register` fornece a funcionalidade de registro de novo usuário.
![account-module-register](../images/account-module-register.png)
### Recuperação de senha e redefinição de senha
A página `/Account/ForgotPassword` fornece uma maneira de enviar um link de redefinição de senha para o endereço de e-mail do usuário. O usuário então clica no link e define uma nova senha.
![account-module-forgot-password](../images/account-module-forgot-password.png)
### Gerenciamento de conta
A página `/Account/Manage` é usada para alterar a senha e as informações pessoais do usuário.
![account-module-manage-account](../images/account-module-manage-account.png)
## Integração com o OpenIddict
O pacote [Volo.Abp.Account.Web.OpenIddict](https://www.nuget.org/packages/Volo.Abp.Account.Web.OpenIddict) fornece integração com o OpenIddict. Este pacote já vem instalado com o modelo de inicialização do aplicativo. Consulte a documentação do módulo OpenIddict.
## Integração com o IdentityServer
O pacote [Volo.Abp.Account.Web.IdentityServer](https://www.nuget.org/packages/Volo.Abp.Account.Web.IdentityServer) fornece integração com o IdentityServer. Este pacote já vem instalado com o modelo de inicialização do aplicativo. Consulte a documentação do módulo IdentityServer.
## Logins Sociais/Externos
O módulo de conta já está configurado para lidar com logins sociais ou externos prontamente. Você pode seguir a documentação do ASP.NET Core para adicionar um provedor de login social/externo à sua aplicação.
### Exemplo: Autenticação do Facebook
Siga o documento de integração do Facebook do ASP.NET Core para oferecer suporte ao login do Facebook em sua aplicação.
#### Adicionar o pacote NuGet
Adicione o pacote [Microsoft.AspNetCore.Authentication.Facebook](https://www.nuget.org/packages/Microsoft.AspNetCore.Authentication.Facebook) ao seu projeto. Com base na sua arquitetura, isso pode ser feito no projeto `.Web`, `.IdentityServer` (para configuração em camadas) ou `.Host`.
#### Configurar o provedor
Use o método de extensão `.AddFacebook(...)` no método `ConfigureServices` do seu [módulo](../Module-Development-Basics.md) para configurar o cliente:
````csharp
context.Services.AddAuthentication()
.AddFacebook(facebook =>
{
facebook.AppId = "...";
facebook.AppSecret = "...";
facebook.Scope.Add("email");
facebook.Scope.Add("public_profile");
});
````
> Seria uma prática melhor usar o `appsettings.json` ou o sistema de segredos do usuário do ASP.NET Core para armazenar suas credenciais, em vez de um valor codificado como esse. Siga o documento da Microsoft para aprender a usar os segredos do usuário.

60
docs/pt-BR/Modules/Audit-Logging.md

@ -0,0 +1,60 @@
# Módulo de Registro de Auditoria
O Módulo de Registro de Auditoria basicamente implementa o `IAuditingStore` para salvar os objetos de registro de auditoria em um banco de dados.
> Este documento abrange apenas o módulo de registro de auditoria que persiste os registros de auditoria em um banco de dados. Consulte o documento [registro de auditoria](../Audit-Logging.md) para obter mais informações sobre o sistema de registro de auditoria.
## Como Instalar
Este módulo vem pré-instalado (como pacotes NuGet/NPM). Você pode continuar a usá-lo como pacote e obter atualizações facilmente, ou pode incluir seu código-fonte em sua solução (consulte o comando `get-source` [CLI](../CLI.md)) para desenvolver seu módulo personalizado.
### O Código Fonte
O código fonte deste módulo pode ser acessado [aqui](https://github.com/abpframework/abp/tree/dev/modules/audit-logging). O código fonte é licenciado com [MIT](https://choosealicense.com/licenses/mit/), então você pode usá-lo e personalizá-lo livremente.
## Internos
### Camada de Domínio
#### Agregados
- `AuditLog` (raiz do agregado): Representa um registro de log de auditoria no sistema.
- `EntityChange` (coleção): Entidades alteradas do registro de auditoria.
- `AuditLogAction` (coleção): Ações executadas do registro de auditoria.
#### Repositórios
Os seguintes repositórios personalizados são definidos para este módulo:
- `IAuditLogRepository`
### Provedores de Banco de Dados
#### Comum
##### Prefixo da tabela / coleção e esquema
Todas as tabelas/coleções usam o prefixo `Abp` por padrão. Defina propriedades estáticas na classe `AbpAuditLoggingDbProperties` se você precisar alterar o prefixo da tabela ou definir um nome de esquema (se suportado pelo seu provedor de banco de dados).
##### String de conexão
Este módulo usa `AbpAuditLogging` como nome da string de conexão. Se você não definir uma string de conexão com esse nome, ela será usada a string de conexão `Default`. Consulte a documentação sobre [strings de conexão](https://docs.abp.io/en/abp/latest/Connection-Strings) para obter mais detalhes.
#### Entity Framework Core
##### Tabelas
- **AbpAuditLogs**
- AbpAuditLogActions
- AbpEntityChanges
- AbpEntityPropertyChanges
#### MongoDB
##### Coleções
- **AbpAuditLogs**
## Veja Também
* [Sistema de registro de auditoria](../Audit-Logging.md)

55
docs/pt-BR/Modules/Background-Jobs.md

@ -0,0 +1,55 @@
# Módulo de Tarefas em Segundo Plano
O módulo de Tarefas em Segundo Plano implementa a interface `IBackgroundJobStore` e torna possível usar o gerenciador de tarefas em segundo plano padrão do ABP Framework. Se você não deseja usar este módulo, então você deve implementar a interface `IBackgroundJobStore` por conta própria.
> Este documento aborda apenas o módulo de tarefas em segundo plano que persiste as tarefas em segundo plano em um banco de dados. Consulte o documento [tarefas em segundo plano](../Background-Jobs.md) para obter mais informações sobre o sistema de tarefas em segundo plano.
## Como Instalar
Este módulo vem pré-instalado (como pacotes NuGet/NPM). Você pode continuar a usá-lo como pacote e obter atualizações facilmente, ou pode incluir seu código-fonte em sua solução (consulte o comando `get-source` [CLI](../CLI.md)) para desenvolver seu próprio módulo personalizado.
### O Código Fonte
O código-fonte deste módulo pode ser acessado [aqui](https://github.com/abpframework/abp/tree/dev/modules/background-jobs). O código-fonte é licenciado com [MIT](https://choosealicense.com/licenses/mit/), então você pode usá-lo e personalizá-lo livremente.
## Internos
### Camada de Domínio
#### Agregados
- `BackgroundJobRecord` (raiz do agregado): Representa um registro de tarefa em segundo plano.
#### Repositórios
Os seguintes repositórios personalizados são definidos para este módulo:
- `IBackgroundJobRepository`
### Provedores de Banco de Dados
#### Comum
##### Prefixo da tabela / coleção e esquema
Todas as tabelas/coleções usam o prefixo `Abp` por padrão. Defina propriedades estáticas na classe `BackgroundJobsDbProperties` se você precisar alterar o prefixo da tabela ou definir um nome de esquema (se suportado pelo seu provedor de banco de dados).
##### String de conexão
Este módulo usa `AbpBackgroundJobs` como nome da string de conexão. Se você não definir uma string de conexão com esse nome, ela será usada a string de conexão `Default`. Consulte a documentação sobre [strings de conexão](https://docs.abp.io/en/abp/latest/Connection-Strings) para obter mais detalhes.
#### Entity Framework Core
##### Tabelas
- **AbpBackgroundJobs**
#### MongoDB
##### Coleções
- **AbpBackgroundJobs**
## Veja Também
* [Sistema de tarefas em segundo plano](../Background-Jobs.md)

135
docs/pt-BR/Modules/Cms-Kit/Blogging.md

@ -0,0 +1,135 @@
# Kit CMS: Blogging
A funcionalidade de blogging fornece a interface necessária para gerenciar e renderizar blogs e postagens de blog.
## Habilitando a funcionalidade de blogging
Por padrão, as funcionalidades do Kit CMS estão desabilitadas. Portanto, você precisa habilitar as funcionalidades que deseja antes de começar a usá-lo. Você pode usar o sistema de [Global Feature](../../Global-Features.md) para habilitar/desabilitar as funcionalidades do Kit CMS durante o desenvolvimento. Alternativamente, você pode usar o [Sistema de Funcionalidades](https://docs.abp.io/en/abp/latest/Features) do ABP Framework para desabilitar uma funcionalidade do Kit CMS em tempo de execução.
> Verifique a seção "Como instalar" da documentação do módulo Kit CMS (Index.md#how-to-install) para saber como habilitar/desabilitar as funcionalidades do Kit CMS durante o desenvolvimento.
## Interface do usuário
### Itens do menu
Os seguintes itens de menu são adicionados pela funcionalidade de blogging à aplicação de administração:
* **Blogs**: Página de gerenciamento de blogs.
* **Postagens de blog**: Página de gerenciamento de postagens de blog.
## Páginas
### Blogs
A página de blogs é usada para criar e gerenciar blogs no seu sistema.
![página-de-blogs](../../images/cmskit-module-blogs-page.png)
Uma captura de tela do modal de criação de novo blog:
![edição-de-blogs](../../images/cmskit-module-blogs-edit.png)
**Slug** é a parte da URL do blog. Para este exemplo, a URL raiz do blog se torna `seu-domínio.com/blogs/blog-técnico/`.
- Você pode alterar o slug padrão usando a constante `CmsBlogsWebConsts.BlogRoutePrefix`. Por exemplo, se você definir como `foo`, a URL raiz do blog se torna `seu-domínio.com/foo/blog-técnico/`.
```csharp
public override void PreConfigureServices(ServiceConfigurationContext context)
{
CmsBlogsWebConsts.BlogsRoutePrefix = "foo";
}
```
#### Funcionalidades do blog
A funcionalidade de blog usa algumas das outras funcionalidades do Kit CMS. Você pode habilitar ou desabilitar as funcionalidades clicando na ação de funcionalidades para um blog.
![ação-de-funcionalidades-de-blogs](../../images/cmskit-module-blogs-feature-action.png)
Você pode selecionar/deselecionar as funcionalidades desejadas para as postagens de blog.
![diálogo-de-funcionalidades](../../images/cmskit-module-features-dialog-2.png)
##### Barra de navegação rápida na postagem de blog
Se você habilitar "Barra de navegação rápida nas postagens de blog", será habilitado o índice de rolagem conforme mostrado abaixo.
![índice-de-rolagem](../../images/cmskit-module-features-scroll-index.png)
### Gerenciamento de postagens de blog
Ao criar blogs, você pode gerenciar as postagens de blog nesta página.
![página-de-postagens-de-blog](../../images/cmskit-module-blog-posts-page.png)
Você pode criar e editar uma postagem de blog existente nesta página. Se você habilitar funcionalidades específicas, como tags, poderá definir tags para a postagem de blog nesta página.
![edição-de-postagem-de-blog](../../images/cmskit-module-blog-post-edit.png)
## Internos
### Camada de domínio
#### Agregados
Este módulo segue o guia de [Melhores Práticas e Convenções de Entidades](https://docs.abp.io/en/abp/latest/Best-Practices/Entities).
- `Blog` _(raiz do agregado)_: Apresenta blogs da aplicação.
- `BlogPost` _(raiz do agregado)_: Apresenta postagens de blog nos blogs.
- `BlogFeature` _(raiz do agregado)_: Apresenta o estado de habilitação/desabilitação das funcionalidades do blog, como reações, avaliações, comentários, etc.
#### Repositórios
Este módulo segue o guia de [Melhores Práticas e Convenções de Repositórios](https://docs.abp.io/en/abp/latest/Best-Practices/Repositories). Os seguintes repositórios são definidos para esta funcionalidade:
- `IBlogRepository`
- `IBlogPostRepository`
- `IBlogFeatureRepository`
#### Serviços de domínio
Este módulo segue o guia de [Melhores Práticas e Convenções de Serviços de Domínio](https://docs.abp.io/en/abp/latest/Best-Practices/Domain-Services).
- `BlogManager`
- `BlogPostManager`
- `BlogFeatureManager`
### Camada de aplicação
#### Serviços de aplicação
##### Comum
- `BlogFeatureAppService` _(implementa `IBlogFeatureAppService`)_
##### Administração
- `BlogAdminAppService` _(implementa `IBlogAdminAppService`)_
- `BlogFeatureAdminAppService` _(implementa `IBlogFeatureAdminAppService`)_
- `BlogPostAdminAppService` _(implementa `IBlogPostAdminAppService`)_
##### Público
- `BlogPostPublicAppService` _(implementa `IBlogPostPublicAppService`)_
### Provedores de banco de dados
#### Entity Framework Core
##### Tabelas
- CmsBlogs
- CmsBlogPosts
- CmsBlogFeatures
#### MongoDB
##### Coleções
- CmsBlogs
- CmsBlogPosts
- CmsBlogFeatures
## Extensões de entidade
Verifique a seção "Extensões de Entidade" da documentação do módulo Kit CMS (Index.md#entity-extensions) para saber como estender as entidades da funcionalidade de Blogging do módulo Kit CMS.

144
docs/pt-BR/Modules/Cms-Kit/Comments.md

@ -0,0 +1,144 @@
# Kit CMS: Comentários
O Kit CMS fornece um sistema de **comentários** para adicionar a funcionalidade de comentários a qualquer tipo de recurso, como postagens de blog, produtos, etc.
## Habilitando a funcionalidade de comentários
Por padrão, as funcionalidades do Kit CMS estão desabilitadas. Portanto, você precisa habilitar as funcionalidades desejadas antes de começar a usá-lo. Você pode usar o sistema de [Funcionalidades Globais](../../Global-Features.md) para habilitar/desabilitar as funcionalidades do Kit CMS durante o desenvolvimento. Alternativamente, você pode usar o [Sistema de Funcionalidades](https://docs.abp.io/pt-BR/abp/latest/Features) do ABP Framework para desabilitar uma funcionalidade do Kit CMS em tempo de execução.
> Verifique a seção ["Como instalar" da documentação do módulo Kit CMS](Index.md#como-instalar) para saber como habilitar/desabilitar as funcionalidades do Kit CMS durante o desenvolvimento.
## Opções
O sistema de comentários fornece um mecanismo para agrupar definições de comentários por tipos de entidade. Por exemplo, se você deseja usar o sistema de comentários para postagens de blog e produtos, você precisa definir dois tipos de entidade chamados `BlogPosts` e `Product` e adicionar comentários sob esses tipos de entidade.
`CmsKitCommentOptions` pode ser configurado na camada de domínio, no método `ConfigureServices` do seu [módulo](https://docs.abp.io/pt-BR/abp/latest/Module-Development-Basics). Exemplo:
```csharp
Configure<CmsKitCommentOptions>(options =>
{
options.EntityTypes.Add(new CommentEntityTypeDefinition("Product"));
options.IsRecaptchaEnabled = true; //false por padrão
options.AllowedExternalUrls = new Dictionary<string, List<string>>
{
{
"Product",
new List<string>
{
"https://abp.io/"
}
}
};
});
```
> Se você estiver usando a [Funcionalidade de Blog](Blogging.md), o ABP Framework define automaticamente um tipo de entidade para a funcionalidade de blog. Você pode facilmente substituir ou remover os tipos de entidade predefinidos no método `Configure` como mostrado acima.
Propriedades de `CmsKitCommentOptions`:
- `EntityTypes`: Lista de tipos de entidade (`CmsKitCommentOptions`) definidos no sistema de comentários.
- `IsRecaptchaEnabled`: Esta flag habilita ou desabilita o reCaptcha para o sistema de comentários. Você pode defini-la como **true** se quiser usar o reCaptcha em seu sistema de comentários.
- `AllowedExternalUrls`: Indica as URLs externas permitidas por tipos de entidade, que podem ser incluídas em um comentário. Se for especificado para um determinado tipo de entidade, apenas as URLs externas especificadas serão permitidas nos comentários.
Propriedades de `CommentEntityTypeDefinition`:
- `EntityType`: Nome do tipo de entidade.
## O Widget de Comentários
O sistema de comentários fornece um [widget](../../UI/AspNetCore/Widgets.md) de comentários para permitir que os usuários enviem comentários para recursos em sites públicos. Você pode simplesmente colocar o widget em uma página como abaixo.
```csharp
@await Component.InvokeAsync(typeof(CommentingViewComponent), new
{
entityType = "Product",
entityId = "...",
isReadOnly = false,
referralLinks = new [] {"nofollow"}
})
```
`entityType` foi explicado na seção anterior. `entityId` deve ser o id único do produto, neste exemplo. Se você tiver uma entidade Produto, você pode usar seu Id aqui. `referralLinks` é um parâmetro opcional. Você pode usar este parâmetro para adicionar valores (como "nofollow", "noreferrer" ou qualquer outro valor) aos atributos [rel](https://developer.mozilla.org/pt-BR/docs/Web/HTML/Attributes/rel) dos links.
## Interface do Usuário
### Itens de Menu
Os seguintes itens de menu são adicionados pela funcionalidade de comentários à aplicação de administração:
* **Comentários**: Abre a página de gerenciamento de comentários.
### Páginas
#### Gerenciamento de Comentários
Você pode visualizar e gerenciar comentários nesta página.
![comment-page](../../images/cmskit-module-comment-page.png)
Você também pode visualizar e gerenciar respostas nesta página.
![comments-detail](../../images/cmskit-module-comments-detail.png)
## Internos
### Camada de Domínio
#### Agregados
Este módulo segue o guia de [Melhores Práticas e Convenções de Entidades](https://docs.abp.io/pt-BR/abp/latest/Best-Practices/Entities).
##### Comentário
Um comentário representa um comentário escrito por um usuário.
- `Comment` (raiz do agregado): Representa um comentário escrito no sistema.
#### Repositórios
Este módulo segue o guia de [Melhores Práticas e Convenções de Repositórios](https://docs.abp.io/pt-BR/abp/latest/Best-Practices/Repositories).
Os seguintes repositórios personalizados são definidos para esta funcionalidade:
- `ICommentRepository`
#### Serviços de Domínio
Este módulo segue o guia de [Melhores Práticas e Convenções de Serviços de Domínio](https://docs.abp.io/pt-BR/abp/latest/Best-Practices/Domain-Services).
##### Gerenciador de Comentários
`CommentManager` é usado para realizar algumas operações para a raiz do agregado `Comment`.
### Camada de Aplicação
#### Serviços de Aplicação
- `CommentAdminAppService` (implementa `ICommentAdminAppService`): Implementa os casos de uso do sistema de gerenciamento de comentários, como listar ou remover comentários, etc.
- `CommentPublicAppService` (implementa `ICommentPublicAppService`): Implementa os casos de uso do sistema de gerenciamento de comentários em sites públicos, como listar comentários, adicionar comentários, etc.
### Provedores de Banco de Dados
#### Comum
##### Prefixo de tabela / coleção e esquema
Todas as tabelas/coleções usam o prefixo `Cms` por padrão. Defina propriedades estáticas na classe `CmsKitDbProperties` se você precisar alterar o prefixo da tabela ou definir um nome de esquema (se suportado pelo seu provedor de banco de dados).
##### String de conexão
Este módulo usa `CmsKit` como nome da string de conexão. Se você não definir uma string de conexão com esse nome, ela será usada a string de conexão `Default`.
Consulte a documentação de [strings de conexão](https://docs.abp.io/pt-BR/abp/latest/Connection-Strings) para obter detalhes.
#### Entity Framework Core
##### Tabelas
- CmsComments
#### MongoDB
##### Coleções
- **CmsComments**

137
docs/pt-BR/Modules/Cms-Kit/Dynamic-Widget.md

@ -0,0 +1,137 @@
# Widget Dinâmico
O kit CMS fornece um [widget](https://docs.abp.io/en/abp/latest/UI/AspNetCore/Widgets) dinâmico usado para renderizar os componentes previamente desenvolvidos pelo software no conteúdo das páginas e postagens de blog. Isso significa que você pode usar conteúdo dinâmico em conteúdo estático. Vamos mencionar como você pode fazer isso. Você tem duas opções para definir o widget no sistema: escrevendo e usando a interface do usuário.
### Adicionando o widget
Primeiramente, mostraremos como usar o sistema de widgets escrevendo manualmente no conteúdo das páginas e postagens de blog.
Vamos definir o componente de visualização
```csharp
[Widget]
[ViewComponent(Name = "CmsToday")]
public class TodayViewComponent : AbpViewComponent
{
public IViewComponentResult Invoke()
{
return View("~/ViewComponents/Today.cshtml",
new TodayViewComponent());
}
}
```
```html
@model Volo.CmsKit.ViewComponents.TodayViewComponent
<p>Bem-vindo ao componente de hoje</p>
<p>@DateTime.Now.ToString()</p>
```
Agora é hora de configurar no arquivo YourModule.cs
```csharp
Configure<CmsKitContentWidgetOptions>(options =>
{
options.AddWidget("Today","CmsToday");
});
```
Agora você está pronto para adicionar seu widget escrevendo.
[Widget Type="Today"]
Após concluir as etapas acima, você pode ver a saída à direita da captura de tela abaixo.
![cmskit-without-parameter.png](../../images/cmskit-without-parameter.png)
### Adicionando usando a interface do usuário
Agora mencionaremos a segunda opção, usando a interface do usuário.
Uma vez que escrever essas definições pode resultar em alguns erros, adicionamos um novo recurso para usar o sistema de widgets facilmente. À direita do editor, você verá o botão `W` personalizado para adicionar um widget dinâmico, como na imagem abaixo. Não se esqueça, por favor, que este é o modo de design e você precisa visualizar sua página no modo de visualização após salvar. Além disso, a guia `Preview` no editor estará pronta para verificar sua saída facilmente para configurações de widget nos recursos seguintes.
![cms-kit-page-editor](../../images/cms-kit-page-editor.png)
### Adicionando usando a interface do usuário com parâmetros
Vamos melhorar o exemplo acima adicionando um novo parâmetro chamado formato. Com esse recurso, podemos usar o sistema de widgets com muitos cenários diferentes, mas sem prolongar o documento. Além disso, esses exemplos podem ser expandidos com injeção de dependência e obtenção de valores do banco de dados, mas usaremos um exemplo básico. Vamos adicionar o parâmetro de formato para personalizar a data.
```csharp
[Widget]
[ViewComponent(Name = "CmsToday")]
public class TodayViewComponent : AbpViewComponent
{
public string Format { get; set; }
public IViewComponentResult Invoke(string format)
{
return View("~/ViewComponents/Today.cshtml",
new TodayViewComponent() { Format = format });
}
}
```
```html
@model Volo.CmsKit.ViewComponents.TodayViewComponent
<p>Bem-vindo ao componente de hoje</p>
<p>@DateTime.Now.ToString(Format)</p>
```
Vamos definir o componente de formato.
```csharp
[Widget]
[ViewComponent(Name = "Format")]
public class FormatViewComponent : AbpViewComponent
{
public IViewComponentResult Invoke()
{
return View("~/ViewComponents/Format.cshtml",
new FormatViewModel());
}
}
public class FormatViewModel
{
[DisplayName("Formate sua data no componente")]
public string Format { get; set; }
}
```
> Nota importante: Para obter as propriedades corretamente, você deve definir a propriedade `name` na página razor ou pode usar o componente ABP. O ABP lida com isso automaticamente.
```html
@using Volo.CmsKit.ViewComponents
@model FormatViewModel
<div>
<abp-input asp-for="Format" />
</div>
```
```csharp
Configure<CmsKitContentWidgetOptions>(options =>
{
options.AddWidget("Today", "CmsToday", "Format");
});
```
![cmskit-module-editor-parameter](../../images/cmskit-module-editor-parameter.png)
Nesta imagem, após escolher seu widget (em outro caso, ele muda automaticamente de acordo com sua configuração, o meu é `Today`. Seu nome de parâmetro é `parameterWidgetName` e seu valor é `Format`) você verá o próximo widget. Insira valores de entrada ou escolha-os e clique em `Add`. Você verá a saída sublinhada no editor. À direita da imagem, você também pode ver sua saída pré-visualizada.
Você pode editar essa saída manualmente se fizer algum código errado para isso (valor incorreto ou erro de digitação), você não verá o widget, mesmo assim, sua página será visualizada com sucesso.
## Opções
Para configurar o widget, você deve definir o código abaixo no arquivo YourModule.cs
```csharp
Configure<CmsKitContentWidgetOptions>(options =>
{
options.AddWidget(widgetType: "Today", widgetName: "CmsToday", parameterWidgetName: "Format");
});
```
Vamos analisar esses parâmetros em detalhes
* `widgetType` é usado para o usuário final e nomes mais legíveis. A palavra em negrito a seguir representa o widgetType.
[Widget Type="**Today**" Format="yyyy-dd-mm HH:mm:ss"].
* `widgetName` é usado para o nome do seu widget usado no código para o nome do `ViewComponent`.
* `parameterWidgetName` é usado no lado do componente do editor para ver no modal `Add Widget`.
Após escolher o tipo de widget na lista suspensa (agora apenas definido `Format`) e renderizar este widget automaticamente. É necessário apenas para ver a interface do usuário uma vez usando parâmetros.

72
docs/pt-BR/Modules/Cms-Kit/Global-Resources.md

@ -0,0 +1,72 @@
# CMS Kit: Recursos Globais
O sistema de Recursos Globais do CMS Kit permite adicionar estilos e scripts globais dinamicamente.
## Habilitando o Recurso de Recursos Globais
Por padrão, os recursos do CMS Kit estão desabilitados. Portanto, você precisa habilitar os recursos que deseja antes de começar a usá-lo. Você pode usar o sistema de [Recursos Globais](../../Global-Features.md) para habilitar/desabilitar os recursos do CMS Kit durante o desenvolvimento. Alternativamente, você pode usar o [Sistema de Recursos](https://docs.abp.io/en/abp/latest/Features) do ABP Framework para desabilitar um recurso do CMS Kit em tempo de execução.
> Verifique a seção "Como Instalar" da documentação do Módulo CMS Kit para saber como habilitar/desabilitar os recursos do CMS Kit durante o desenvolvimento.
## A Interface do Usuário
### Itens do Menu
O módulo CMS Kit adiciona os seguintes itens ao menu principal, sob o item de menu *Recursos Globais*:
* **Recursos Globais**: Página de gerenciamento de recursos globais.
A classe `CmsKitAdminMenus` possui as constantes para os nomes dos itens do menu.
### Página de Recursos Globais
A página de Recursos Globais é usada para gerenciar estilos e scripts globais no sistema.
![cms-kit-global-resources-page](../../images/cmskit-module-global-resources-page.png)
# Internos
## Camada de Domínio
#### Agregados
Este módulo segue o guia de [Melhores Práticas e Convenções de Entidades](https://docs.abp.io/en/abp/latest/Best-Practices/Entities).
- `GlobalResource` (raiz do agregado): Armazena um recurso.
#### Repositórios
Este módulo segue o guia de [Melhores Práticas e Convenções de Repositórios](https://docs.abp.io/en/abp/latest/Best-Practices/Repositories).
Os seguintes repositórios personalizados são definidos para este recurso:
- `IGlobalResourceRepository`
#### Serviços de Domínio
Este módulo segue o guia de [Melhores Práticas e Convenções de Serviços de Domínio](https://docs.abp.io/en/abp/latest/Best-Practices/Domain-Services).
##### Gerenciador de Recursos Globais
`GlobalResourceManager` é usado para realizar operações para a raiz do agregado `GlobalResource`.
### Camada de Aplicação
#### Serviços de Aplicação
- `GlobalResourceAdminAppService` (implementa `IGlobalResourceAdminAppService`): Implementa as operações de gerenciamento do sistema de recursos globais.
- `GlobalResourcePublicAppService` (implementa `IGlobalResourcePublicAppService`): Implementa os casos de uso públicos do sistema de recursos globais.
#### Banco de Dados
#### Entity Framework Core
##### Tabelas
- CmsGlobalResources
#### MongoDB
##### Coleções
- CmsGlobalResources

143
docs/pt-BR/Modules/Cms-Kit/Index.md

@ -0,0 +1,143 @@
# Módulo CMS Kit
Este módulo fornece recursos de CMS (Sistema de Gerenciamento de Conteúdo) para sua aplicação. Ele fornece **blocos de construção principais** e **sub-sistemas** totalmente funcionais para criar seu próprio site com recursos de CMS habilitados, ou usar os blocos de construção em seus sites com qualquer finalidade.
> **Este módulo está atualmente disponível apenas para a interface MVC / Razor Pages**. Embora não haja um pacote oficial do Blazor, ele também pode funcionar em uma interface Blazor Server, pois uma interface Blazor Server é na verdade um aplicativo híbrido que é executado em um aplicativo ASP.NET Core MVC / Razor Pages.
Os seguintes recursos estão atualmente disponíveis:
* Fornece um sistema de gerenciamento de [**páginas**](Pages.md) para gerenciar páginas dinâmicas com URLs dinâmicos.
* Fornece um sistema de [**blog**](Blogging.md) para criar e publicar postagens de blog com suporte a vários blogs.
* Fornece um sistema de [**marcação**](Tags.md) para marcar qualquer tipo de recurso, como uma postagem de blog.
* Fornece um sistema de [**comentários**](Comments.md) para adicionar recursos de comentários a qualquer tipo de recurso, como postagem de blog ou uma página de avaliação de produto.
* Fornece um sistema de [**reações**](Reactions.md) para adicionar recursos de reações (emojis) a qualquer tipo de recurso, como uma postagem de blog ou um comentário.
* Fornece um sistema de [**classificação**](Ratings.md) para adicionar recursos de classificação a qualquer tipo de recurso.
* Fornece um sistema de [**menu**](Menus.md) para gerenciar menus públicos dinamicamente.
* Fornece um sistema de [**recursos globais**](Global-Resources.md) para adicionar estilos e scripts globais dinamicamente.
* Fornece um sistema de [**widget dinâmico**](Dynamic-Widget.md) para criar widgets dinâmicos para páginas e postagens de blog.
> Você pode clicar nos links de recursos acima para entender e aprender como usá-los.
Todos os recursos podem ser usados individualmente. Se você desabilitar um recurso, ele desaparecerá completamente de sua aplicação, inclusive das tabelas do banco de dados, com a ajuda do sistema [Recursos Globais](../../Global-Features.md).
## Pré-requisitos
- Este módulo depende do módulo [BlobStoring](../../Blob-Storing.md) para armazenar conteúdo de mídia.
> Certifique-se de que o módulo `BlobStoring` esteja instalado e que pelo menos um provedor esteja configurado corretamente. Para obter mais informações, consulte a [documentação](../../Blob-Storing.md).
- O CMS Kit usa o [cache distribuído](../../Caching.md) para responder mais rapidamente.
> É altamente recomendado usar um cache distribuído, como o [Redis](../../Redis-Cache.md), para garantir a consistência dos dados em implantações distribuídas/clusterizadas.
## Como instalar
O [ABP CLI](../../CLI.md) permite instalar um módulo em uma solução usando o comando `add-module`. Você pode instalar o módulo CMS Kit em um terminal de linha de comando com o seguinte comando:
```bash
abp add-module Volo.CmsKit --skip-db-migrations
```
> Por padrão, o Cms-Kit está desabilitado pelo `GlobalFeature`. Por causa disso, a migração inicial estará vazia. Portanto, você pode pular a migração adicionando `--skip-db-migrations` ao comando de instalação se estiver usando o Entity Framework Core. Após habilitar o recurso global Cms-Kit, adicione uma nova migração.
Após o processo de instalação, abra a classe `GlobalFeatureConfigurator` no projeto `Domain.Shared` de sua solução e coloque o seguinte código no método `Configure` para habilitar todos os recursos no módulo CMS Kit.
```csharp
GlobalFeatureManager.Instance.Modules.CmsKit(cmsKit =>
{
cmsKit.EnableAll();
});
```
Em vez de habilitar todos, você pode preferir habilitar os recursos um por um. O exemplo a seguir habilita apenas os recursos de [marcadores](Tags.md) e [comentários](Comments.md):
````csharp
GlobalFeatureManager.Instance.Modules.CmsKit(cmsKit =>
{
cmsKit.Tags.Enable();
cmsKit.Comments.Enable();
});
````
> Se você estiver usando o Entity Framework Core, não se esqueça de adicionar uma nova migração e atualizar seu banco de dados.
## Os Pacotes
Este módulo segue o [guia de melhores práticas para desenvolvimento de módulos](https://docs.abp.io/en/abp/latest/Best-Practices/Index) e consiste em vários pacotes NuGet e NPM. Consulte o guia se você quiser entender os pacotes e as relações entre eles.
Os pacotes do CMS kit são projetados para vários cenários de uso. Se você verificar os [pacotes do CMS kit](https://www.nuget.org/packages?q=Volo.CmsKit), verá que alguns pacotes têm sufixos `Admin` e `Public`. A razão é que o módulo possui duas camadas de aplicação, considerando que eles podem ser usados em diferentes tipos de aplicativos. Essas camadas de aplicação usam uma única camada de domínio:
- Os pacotes `Volo.CmsKit.Admin.*` contêm as funcionalidades necessárias para aplicativos de administração (back office).
- Os pacotes `Volo.CmsKit.Public.*` contêm as funcionalidades usadas em sites públicos onde os usuários leem postagens de blog ou deixam comentários.
- Os pacotes `Volo.CmsKit.*` (sem sufixo Admin/Public) são chamados de pacotes unificados. Os pacotes unificados são atalhos para adicionar pacotes Admin e Public (da camada relacionada) separadamente. Se você tiver um único aplicativo para administração e site público, você pode usar esses pacotes.
## Internos
### Prefixo de tabela / coleção e esquema
Todas as tabelas/coleções usam o prefixo `Cms` por padrão. Defina propriedades estáticas na classe `CmsKitDbProperties` se você precisar alterar o prefixo da tabela ou definir um nome de esquema (se suportado pelo provedor de banco de dados).
### String de conexão
Este módulo usa `CmsKit` como nome da string de conexão. Se você não definir uma string de conexão com esse nome, ela será substituída pela string de conexão `Default`.
Consulte a documentação sobre [strings de conexão](https://docs.abp.io/en/abp/latest/Connection-Strings) para obter mais detalhes.
## Extensões de Entidade
O sistema de extensão de entidade do módulo (https://docs.abp.io/en/abp/latest/Module-Entity-Extensions) é um sistema de extensão **de alto nível** que permite **definir novas propriedades** para entidades existentes dos módulos dependentes. Ele automaticamente **adiciona propriedades à entidade**, **banco de dados**, **API HTTP** e **interface do usuário** em um único ponto.
Para estender as entidades do módulo CMS Kit, abra a classe `YourProjectNameModuleExtensionConfigurator` dentro do projeto `DomainShared` e altere o método `ConfigureExtraProperties` conforme mostrado abaixo.
```csharp
public static void ConfigureExtraProperties()
{
OneTimeRunner.Run(() =>
{
ObjectExtensionManager.Instance.Modules()
.ConfigureCmsKit(cmsKit =>
{
cmsKit.ConfigureBlog(plan => // estende a entidade Blog
{
plan.AddOrUpdateProperty<string>( //tipo de propriedade: string
"BlogDescription", //nome da propriedade
property => {
//regras de validação
property.Attributes.Add(new RequiredAttribute()); //adiciona o atributo obrigatório à propriedade definida
//...outras configurações para esta propriedade
}
);
});
cmsKit.ConfigureBlogPost(blogPost => // estende a entidade BlogPost
{
blogPost.AddOrUpdateProperty<string>( //tipo de propriedade: string
"BlogPostDescription", //nome da propriedade
property => {
//regras de validação
property.Attributes.Add(new RequiredAttribute()); //adiciona o atributo obrigatório à propriedade definida
property.Attributes.Add(
new StringLengthAttribute(MyConsts.MaximumDescriptionLength) {
MinimumLength = MyConsts.MinimumDescriptionLength
}
);
//...outras configurações para esta propriedade
}
);
});
});
});
}
```
* O método `ConfigureCmsKit(...)` é usado para configurar as entidades do módulo CMS Kit.
* `cmsKit.ConfigureBlog(...)` é usado para configurar a entidade **Blog** do módulo CMS Kit. Você pode adicionar ou atualizar suas propriedades extras na entidade **Blog**.
* `cmsKit.ConfigureBlogPost(...)` é usado para configurar a entidade **BlogPost** do módulo CMS Kit. Você pode adicionar ou atualizar suas propriedades extras na entidade **BlogPost**.
* Você também pode definir algumas regras de validação para a propriedade que você definiu. No exemplo acima, foram adicionados `RequiredAttribute` e `StringLengthAttribute` para a propriedade chamada **"BlogPostDescription"**.
* Quando você define a nova propriedade, ela será automaticamente adicionada à **Entidade**, **API HTTP** e **UI** para você.
* Depois de definir uma propriedade, ela aparece nos formulários de criação e atualização da entidade relacionada.
* As novas propriedades também aparecem na tabela de dados da página relacionada.

90
docs/pt-BR/Modules/Cms-Kit/Menus.md

@ -0,0 +1,90 @@
# CMS Kit: Menus
O sistema de menus do CMS Kit permite gerenciar menus públicos de forma dinâmica.
## Habilitando o recurso de menu
Por padrão, os recursos do CMS Kit estão desabilitados. Portanto, é necessário habilitar os recursos desejados antes de começar a usá-lo. Você pode usar o sistema de [Recursos Globais](../../Global-Features.md) para habilitar/desabilitar os recursos do CMS Kit durante o desenvolvimento. Alternativamente, você pode usar o [Sistema de Recursos](https://docs.abp.io/en/abp/latest/Features) do ABP Framework para desabilitar um recurso do CMS Kit em tempo de execução.
> Verifique a seção "Como instalar" da documentação do módulo CMS Kit (Index.md#how-to-install) para saber como habilitar/desabilitar os recursos do CMS Kit durante o desenvolvimento.
## A interface do usuário
### Itens de menu
O módulo CMS Kit adiciona os seguintes itens ao menu principal, sob o item de menu *CMS*:
* **Menus**: Página de gerenciamento de menus.
A classe `CmsKitAdminMenus` possui as constantes para os nomes dos itens de menu.
### Menus
#### Gerenciamento de menus
A página de menus é usada para gerenciar menus públicos dinâmicos no sistema.
![cms-kit-menus-page](../../images/cmskit-module-menus-page.png)
Os itens de menu criados serão visíveis no lado público do site, como mostrado abaixo:
![cms-kit-public-menus](../../images//cmskit-module-menus-public.png)
## Internos
### Camada de domínio
#### Agregados
Este módulo segue o guia de [Melhores Práticas e Convenções de Entidades](https://docs.abp.io/en/abp/latest/Best-Practices/Entities).
- `MenuItem` (raiz do agregado): Um item de menu representa um único nó na árvore de menus.
#### Repositórios
Este módulo segue o guia de [Melhores Práticas e Convenções de Repositórios](https://docs.abp.io/en/abp/latest/Best-Practices/Repositories).
Os seguintes repositórios personalizados são definidos para este recurso:
- `IMenuItemRepository`
#### Serviços de domínio
Este módulo segue o guia de [Melhores Práticas e Convenções de Serviços de Domínio](https://docs.abp.io/en/abp/latest/Best-Practices/Domain-Services).
##### Gerenciador de itens de menu
`MenuItemManager` é usado para realizar algumas operações para a raiz do agregado `MenuItemManager`.
### Camada de aplicação
#### Serviços de aplicação
- `MenuItemAdminAppService` (implementa `IMenuItemAdminAppService`): Implementa as operações de gerenciamento do sistema de menus.
- `MenuItemPublicAppService` (implementa `IMenuItemPublicAppService`): Implementa os casos de uso públicos do sistema de menus.
### Provedores de banco de dados
#### Comum
##### Prefixo de tabela / coleção e esquema
Todas as tabelas/coleções usam o prefixo `Cms` por padrão. Defina propriedades estáticas na classe `CmsKitDbProperties` se você precisar alterar o prefixo da tabela ou definir um nome de esquema (se suportado pelo seu provedor de banco de dados).
##### String de conexão
Este módulo usa `CmsKit` como nome da string de conexão. Se você não definir uma string de conexão com esse nome, ela será substituída pela string de conexão `Default`.
Consulte a documentação sobre [strings de conexão](https://docs.abp.io/en/abp/latest/Connection-Strings) para obter mais detalhes.
#### Entity Framework Core
##### Tabelas
- CmsMenuItems
#### MongoDB
##### Coleções
- CmsMenuItems

33
docs/pt-BR/Modules/Cms-Kit/Pages.md

@ -0,0 +1,33 @@
# Kit CMS: Páginas
O sistema de páginas do Kit CMS permite que você crie páginas dinâmicas especificando URLs, que é a funcionalidade fundamental de um CMS.
## Habilitando a Funcionalidade de Páginas
Por padrão, as funcionalidades do Kit CMS estão desabilitadas. Portanto, você precisa habilitar as funcionalidades que deseja antes de começar a usá-lo. Você pode usar o sistema de [Funcionalidades Globais](../../Global-Features.md) para habilitar/desabilitar as funcionalidades do Kit CMS durante o desenvolvimento. Alternativamente, você pode usar o [Sistema de Funcionalidades](https://docs.abp.io/en/abp/latest/Features) do ABP Framework para desabilitar uma funcionalidade do Kit CMS em tempo de execução.
> Verifique a seção "Como Instalar" da documentação do Módulo Kit CMS (Index.md#how-to-install) para saber como habilitar/desabilitar as funcionalidades do Kit CMS durante o desenvolvimento.
## A Interface do Usuário
### Itens do Menu
O módulo Kit CMS adiciona os seguintes itens ao menu principal, sob o item de menu *CMS*:
* **Páginas**: Página de gerenciamento de páginas.
A classe `CmsKitAdminMenus` possui as constantes para os nomes dos itens do menu.
### Páginas
#### Gerenciamento de Páginas
A página **Páginas** é usada para gerenciar páginas dinâmicas no sistema. Você pode criar/editar páginas com rotas e conteúdos dinâmicos nesta página:
![pages-edit](../../images/cmskit-module-pages-edit.png)
Depois de criar páginas, você pode definir uma delas como página inicial. Então, sempre que alguém navegar para a página inicial do seu aplicativo, eles verão o conteúdo dinâmico da página que você definiu nesta página.
![pages-page](../../images/cmskit-module-pages-page.png)
Além disso, quando você cria uma página, você pode acessá-la através da URL `/{slug}`.

111
docs/pt-BR/Modules/Cms-Kit/Ratings.md

@ -0,0 +1,111 @@
# Sistema de Avaliação
O kit CMS fornece um sistema de **avaliação** para adicionar recursos de avaliação a qualquer tipo de recurso, como postagens de blog, comentários, etc. Aqui está como o componente de avaliação se parece em uma página de exemplo:
![avaliações](../../images/cmskit-module-ratings.png)
## Habilitando o Recurso de Avaliação
Por padrão, os recursos do CMS Kit estão desabilitados. Portanto, você precisa habilitar os recursos que deseja antes de começar a usá-lo. Você pode usar o sistema de [Recurso Global](../../Global-Features.md) para habilitar/desabilitar os recursos do CMS Kit durante o desenvolvimento. Alternativamente, você pode usar o [Sistema de Recursos](https://docs.abp.io/en/abp/latest/Features) do ABP Framework para desabilitar um recurso do CMS Kit em tempo de execução.
> Verifique a seção ["Como Instalar" da documentação do Módulo CMS Kit](Index.md#how-to-install) para ver como habilitar/desabilitar os recursos do CMS Kit durante o desenvolvimento.
## Opções
O sistema de avaliação fornece um mecanismo para agrupar avaliações por tipos de entidade. Por exemplo, se você deseja usar o sistema de avaliação para produtos, você precisa definir um tipo de entidade chamado `Produto` e, em seguida, adicionar avaliações sob o tipo de entidade definido.
`CmsKitRatingOptions` pode ser configurado na camada de domínio, no método `ConfigureServices` do seu [módulo](https://docs.abp.io/en/abp/latest/Module-Development-Basics). Exemplo:
```csharp
Configure<CmsKitRatingOptions>(options =>
{
options.EntityTypes.Add(new RatingEntityTypeDefinition("Produto"));
});
```
> Se você estiver usando o [Recurso de Blog](Blogging.md), o framework ABP define automaticamente um tipo de entidade para o recurso de blog. Você pode facilmente substituir ou remover os tipos de entidade predefinidos no método `Configure` como mostrado acima.
Propriedades de `CmsKitRatingOptions`:
- `EntityTypes`: Lista de tipos de entidade definidos (`RatingEntityTypeDefinition`) no sistema de avaliação.
Propriedades de `RatingEntityTypeDefinition`:
- `EntityType`: Nome do tipo de entidade.
## O Widget de Avaliação
O sistema de avaliação fornece um widget de avaliação para permitir que os usuários enviem avaliações para recursos em sites públicos. Você pode simplesmente colocar o widget em uma página como abaixo.
```csharp
@await Component.InvokeAsync(typeof(RatingViewComponent), new
{
entityType = "Produto",
entityId = "entityId",
isReadOnly = false
})
```
`entityType` foi explicado na seção anterior. `entityId` deve ser o id único do produto, neste exemplo. Se você tiver uma entidade Produto, você pode usar seu Id aqui.
# Internos
## Camada de Domínio
#### Agregados
Este módulo segue o guia de [Melhores Práticas e Convenções de Entidades](https://docs.abp.io/en/abp/latest/Best-Practices/Entities).
##### Avaliação
Uma avaliação representa uma avaliação dada por um usuário.
- `Avaliação` (raiz do agregado): Representa uma avaliação dada no sistema.
#### Repositórios
Este módulo segue o guia de [Melhores Práticas e Convenções de Repositórios](https://docs.abp.io/en/abp/latest/Best-Practices/Repositories).
Os seguintes repositórios personalizados são definidos para este recurso:
- `IRatingRepository`
#### Serviços de Domínio
Este módulo segue o guia de [Melhores Práticas e Convenções de Serviços de Domínio](https://docs.abp.io/en/abp/latest/Best-Practices/Domain-Services).
##### Gerenciador de Reações
`RatingManager` é usado para realizar algumas operações para a raiz do agregado `Avaliação`.
### Camada de Aplicação
#### Serviços de Aplicação
- `RatingPublicAppService` (implementa `IRatingPublicAppService`): Implementa os casos de uso do sistema de avaliação.
### Provedores de Banco de Dados
#### Comum
##### Prefixo da tabela / coleção e esquema
Todas as tabelas/coleções usam o prefixo `Cms` por padrão. Defina propriedades estáticas na classe `CmsKitDbProperties` se você precisar alterar o prefixo da tabela ou definir um nome de esquema (se suportado pelo seu provedor de banco de dados).
##### String de conexão
Este módulo usa `CmsKit` como nome da string de conexão. Se você não definir uma string de conexão com esse nome, ela será usada a string de conexão `Default`.
Consulte a documentação de [strings de conexão](https://docs.abp.io/en/abp/latest/Connection-Strings) para obter detalhes.
#### Entity Framework Core
##### Tabelas
- CmsRatings
#### MongoDB
##### Coleções
- **CmsRatings**

126
docs/pt-BR/Modules/Cms-Kit/Reactions.md

@ -0,0 +1,126 @@
# Sistema de Reações
O kit CMS fornece um sistema de **reações** para adicionar recursos de reações a qualquer tipo de recurso, como postagens de blog ou comentários.
O componente de reação permite que os usuários reajam ao seu conteúdo por meio de ícones/emojis pré-definidos. Aqui está como o componente de reações pode parecer:
![reactions](../../images/cmskit-module-reactions.png)
Você também pode personalizar os ícones de reação mostrados no componente de reação.
## Habilitando o Recurso de Reação
Por padrão, os recursos do CMS Kit estão desabilitados. Portanto, você precisa habilitar os recursos que deseja antes de começar a usá-lo. Você pode usar o sistema de [Recurso Global](../../Global-Features.md) para habilitar/desabilitar recursos do CMS Kit durante o desenvolvimento. Alternativamente, você pode usar o [Sistema de Recursos](https://docs.abp.io/en/abp/latest/Features) do ABP Framework para desabilitar um recurso do CMS Kit em tempo de execução.
> Verifique a seção ["Como Instalar" da documentação do Módulo CMS Kit](Index.md#how-to-install) para ver como habilitar/desabilitar recursos do CMS Kit durante o desenvolvimento.
## Opções
O sistema de reação fornece um mecanismo para agrupar reações por tipos de entidade. Por exemplo, se você deseja usar o sistema de reação para produtos, você precisa definir um tipo de entidade chamado `Produto` e, em seguida, adicionar reações sob o tipo de entidade definido.
`CmsKitReactionOptions` pode ser configurado na camada de domínio, no método `ConfigureServices` do seu [módulo](https://docs.abp.io/en/abp/latest/Module-Development-Basics). Exemplo:
```csharp
Configure<CmsKitReactionOptions>(options =>
{
options.EntityTypes.Add(
new ReactionEntityTypeDefinition(
"Produto",
reactions: new[]
{
new ReactionDefinition(StandardReactions.Smile),
new ReactionDefinition(StandardReactions.ThumbsUp),
new ReactionDefinition(StandardReactions.ThumbsDown),
new ReactionDefinition(StandardReactions.Confused),
new ReactionDefinition(StandardReactions.Eyes),
new ReactionDefinition(StandardReactions.Heart)
}));
});
```
> Se você estiver usando os recursos [Comentário](Comments.md) ou [Blogging](Blogging.md), o framework ABP define reações predefinidas para esses recursos automaticamente.
Propriedades de `CmsKitReactionOptions`:
- `EntityTypes`: Lista de tipos de entidade definidos (`CmsKitReactionOptions`) no sistema de reação.
Propriedades de `ReactionEntityTypeDefinition`:
- `EntityType`: Nome do tipo de entidade.
- `Reactions`: Lista de reações definidas (`ReactionDefinition`) no tipo de entidade.
## O Widget de Reações
O sistema de reação fornece um widget de reação para permitir que os usuários enviem reações para recursos. Você pode colocar o widget em uma página da seguinte forma:
```csharp
@await Component.InvokeAsync(typeof(ReactionSelectionViewComponent), new
{
entityType = "Produto",
entityId = "..."
})
```
`entityType` foi explicado na seção anterior. `entityId` deve ser o id único do produto, neste exemplo. Se você tiver uma entidade Produto, pode usar seu Id aqui.
# Internos
## Camada de Domínio
#### Agregados
Este módulo segue o guia de [Melhores Práticas e Convenções de Entidades](https://docs.abp.io/en/abp/latest/Best-Practices/Entities).
##### UserReaction
Uma reação do usuário representa uma reação específica de um usuário.
- `UserReaction` (raiz do agregado): Representa uma reação específica no sistema.
#### Repositórios
Este módulo segue o guia de [Melhores Práticas e Convenções de Repositórios](https://docs.abp.io/en/abp/latest/Best-Practices/Repositories).
Os seguintes repositórios personalizados são definidos para este recurso:
- `IUserReactionRepository`
#### Serviços de Domínio
Este módulo segue o guia de [Melhores Práticas e Convenções de Serviços de Domínio](https://docs.abp.io/en/abp/latest/Best-Practices/Domain-Services).
##### Reaction Manager
`ReactionManager` é usado para realizar algumas operações para a raiz do agregado `UserReaction`.
### Camada de Aplicação
#### Serviços de Aplicação
- `ReactionPublicAppService` (implementa `IReactionPublicAppService`): Implementa os casos de uso do sistema de reação.
### Provedores de Banco de Dados
#### Comum
##### Prefixo da tabela/collection e esquema
Todas as tabelas/collections usam o prefixo `Cms` por padrão. Defina propriedades estáticas na classe `CmsKitDbProperties` se você precisar alterar o prefixo da tabela ou definir um nome de esquema (se suportado pelo seu provedor de banco de dados).
##### String de conexão
Este módulo usa `CmsKit` como nome da string de conexão. Se você não definir uma string de conexão com esse nome, ela será usada a string de conexão `Default`.
Consulte a documentação de [strings de conexão](https://docs.abp.io/en/abp/latest/Connection-Strings) para obter detalhes.
#### Entity Framework Core
##### Tabelas
- CmsUserReactions
#### MongoDB
##### Coleções
- **CmsUserReactions**

165
docs/pt-BR/Modules/Cms-Kit/Tags.md

@ -0,0 +1,165 @@
# Gerenciamento de Tags
O CMS Kit fornece um sistema de **tag** para marcar qualquer tipo de recurso, como uma postagem de blog.
## Habilitando o recurso de Gerenciamento de Tags
Por padrão, os recursos do CMS Kit estão desabilitados. Portanto, você precisa habilitar os recursos que deseja antes de começar a usá-lo. Você pode usar o sistema de [Recursos Globais](../../Global-Features.md) para habilitar/desabilitar os recursos do CMS Kit durante o desenvolvimento. Alternativamente, você pode usar o [Sistema de Recursos](https://docs.abp.io/en/abp/latest/Features) do ABP Framework para desabilitar um recurso do CMS Kit em tempo de execução.
> Verifique a seção ["Como instalar" da documentação do Módulo CMS Kit](Index.md#how-to-install) para saber como habilitar/desabilitar os recursos do CMS Kit durante o desenvolvimento.
## Opções
O sistema de tags fornece um mecanismo para agrupar tags por tipos de entidade. Por exemplo, se você deseja usar o sistema de tags para postagens de blog e produtos, você precisa definir dois tipos de entidade chamados `BlogPosts` e `Product` e adicionar tags sob esses tipos de entidade.
`CmsKitTagOptions` pode ser configurado na camada de domínio, no método `ConfigureServices` da sua classe [módulo](https://docs.abp.io/en/abp/latest/Module-Development-Basics).
**Exemplo: Adicionando suporte a tags para produtos**
```csharp
Configure<CmsKitTagOptions>(options =>
{
options.EntityTypes.Add(new TagEntityTypeDefiniton("Product"));
});
```
> Se você estiver usando o [Recurso de Blogging](Blogging.md), o framework ABP define automaticamente um tipo de entidade para o recurso de blog.
Propriedades de `CmsKitTagOptions`:
- `EntityTypes`: Lista de tipos de entidade definidos (`TagEntityTypeDefiniton`) no sistema de tags.
Propriedades de `TagEntityTypeDefiniton`:
- `EntityType`: Nome do tipo de entidade.
- `DisplayName`: O nome de exibição do tipo de entidade. Você pode usar um nome de exibição amigável para mostrar a definição do tipo de entidade no site de administração.
- `CreatePolicies`: Lista de nomes de políticas/permissões que permitem aos usuários criar tags sob o tipo de entidade.
- `UpdatePolicies`: Lista de nomes de políticas/permissões que permitem aos usuários atualizar tags sob o tipo de entidade.
- `DeletePolicies`: Lista de nomes de políticas/permissões que permitem aos usuários excluir tags sob o tipo de entidade.
## O Widget de Tag
O sistema de tags fornece um widget de tag [widget](../../UI/AspNetCore/Widgets.md) para exibir as tags associadas a um recurso que foi configurado para tags. Você pode simplesmente colocar o widget em uma página como a abaixo:
```csharp
@await Component.InvokeAsync(typeof(TagViewComponent), new
{
entityType = "Product",
entityId = "...",
urlFormat = "/products?tagId={TagId}&tagName={TagName}"
})
```
`entityType` foi explicado na seção anterior. Neste exemplo, o `entityId` deve ser o id único do produto. Se você tiver uma entidade `Product`, você pode usar seu Id aqui. `urlFormat` é o formato de string do URL que será gerado para cada tag. Você pode usar os espaços reservados `{TagId}` e `{TagName}` para preencher o URL. Por exemplo, o formato de URL acima preencherá URLs como `/products?tagId=1&tagName=tag1`.
## O Widget de Tags Populares
O sistema de tags fornece um widget de tags populares [widget](../../UI/AspNetCore/Widgets.md) para exibir tags populares de um recurso que foi configurado para tags. Você pode simplesmente colocar o widget em uma página como abaixo:
```csharp
@await Component.InvokeAsync(typeof(PopularTagsViewComponent), new
{
entityType = "Product",
urlFormat = "/products?tagId={TagId}&tagName={TagName}",
maxCount = 10
})
```
`entityType` foi explicado na seção anterior. `urlFormat` foi explicado na seção anterior. `maxCount` é o número máximo de tags a serem exibidas.
## Interface do Usuário
### Itens de Menu
Os seguintes itens de menu são adicionados pelo recurso de tags à aplicação de administração:
* **Tags**: Abre a página de gerenciamento de tags.
### Páginas
#### Gerenciamento de Tags
Esta página pode ser usada para criar, editar e excluir tags para os tipos de entidade.
![tags-page](../../images/cmskit-module-tags-page.png)
Você pode criar ou editar uma tag existente nesta página.
![tag-edit](../../images/cmskit-module-tag-edit.png)
## Internos
### Camada de Domínio
#### Agregados
Este módulo segue o guia de [Melhores Práticas e Convenções de Entidades](https://docs.abp.io/en/abp/latest/Best-Practices/Entities).
##### Tag
Uma tag representa uma tag sob o tipo de entidade.
- `Tag` (raiz do agregado): Representa uma tag no sistema.
##### EntityTag
Uma entidade tag representa uma conexão entre a tag e a entidade marcada.
- `EntityTag`(entidade): Representa uma conexão entre a tag e a entidade marcada.
#### Repositórios
Este módulo segue o guia de [Melhores Práticas e Convenções de Repositórios](https://docs.abp.io/en/abp/latest/Best-Practices/Repositories).
Os seguintes repositórios personalizados são definidos para este recurso:
- `ITagRepository`
- `IEntityTagRepository`
#### Serviços de Domínio
Este módulo segue o guia de [Melhores Práticas e Convenções de Serviços de Domínio](https://docs.abp.io/en/abp/latest/Best-Practices/Domain-Services).
##### Gerenciador de Tags
`TagManager` realiza algumas operações para a raiz do agregado `Tag`.
##### Gerenciador de Entidade Tag
`EntityTagManager` realiza algumas operações para a entidade `EntityTag`.
### Camada de Aplicação
#### Serviços de Aplicação
- `TagAdminAppService` (implementa `ITagAdminAppService`).
- `EntityTagAdminAppService` (implementa `IEntityTagAdminAppService`).
- `TagAppService` (implementa `ITagAppService`).
### Provedores de Banco de Dados
#### Comum
##### Prefixo de Tabela / Coleção e esquema
Todas as tabelas/coleções usam o prefixo `Cms` por padrão. Defina propriedades estáticas na classe `CmsKitDbProperties` se você precisar alterar o prefixo da tabela ou definir um nome de esquema (se suportado pelo seu provedor de banco de dados).
##### String de conexão
Este módulo usa `CmsKit` como nome da string de conexão. Se você não definir uma string de conexão com esse nome, ela será usada a string de conexão `Default`.
Consulte a documentação de [strings de conexão](https://docs.abp.io/en/abp/latest/Connection-Strings) para obter detalhes.
#### Entity Framework Core
##### Tabelas
- CmsTags
- CmsEntityTags
#### MongoDB
##### Coleções
- **CmsTags**
- **CmsEntityTags**

577
docs/pt-BR/Modules/Database-Tables.md

@ -0,0 +1,577 @@
# Tabelas do Banco de Dados
Esta documentação descreve todas as tabelas do banco de dados e seus propósitos. Você pode ler esta documentação para obter conhecimento geral das tabelas do banco de dados que vêm de cada módulo.
## [Módulo de Registro de Auditoria](Audit-Logging.md)
### AbpAuditLogs
Esta tabela armazena informações sobre os registros de auditoria no aplicativo. Cada registro representa um log de auditoria e rastreia as ações realizadas no aplicativo.
### AbpAuditLogActions
Esta tabela armazena informações sobre as ações realizadas no aplicativo, que são registradas para fins de auditoria.
#### Chaves Estrangeiras
| Tabela | Coluna | Descrição |
| --- | --- | --- |
| [AbpAuditLogs](#abpauditlogs) | Id | Vincula cada ação a um log de auditoria específico. |
### AbpEntityChanges
Esta tabela armazena informações sobre as alterações de entidade no aplicativo, que são registradas para fins de auditoria.
#### Chaves Estrangeiras
| Tabela | Coluna | Descrição |
| --- | --- | --- |
| [AbpAuditLogs](#abpauditlogs) | Id | Vincula cada alteração de entidade a um log de auditoria específico. |
### AbpEntityPropertyChanges
Esta tabela armazena informações sobre as alterações de propriedade em entidades no aplicativo, que são registradas para fins de auditoria.
#### Chaves Estrangeiras
| Tabela | Coluna | Descrição |
| --- | --- | --- |
| [AbpEntityChanges](#abpentitychanges) | Id | Vincula cada alteração de propriedade a uma alteração de entidade específica. |
## [Módulo de Tarefas em Segundo Plano](Background-Jobs.md)
### AbpBackgroundJobs
Esta tabela armazena informações sobre as tarefas em segundo plano no aplicativo e facilita seu gerenciamento e rastreamento eficientes. Cada entrada na tabela contém detalhes de uma tarefa em segundo plano, incluindo o nome da tarefa, argumentos, contagem de tentativas, próxima tentativa, última tentativa, status abandonado e prioridade.
## [Módulo de Gerenciamento de Inquilinos](Tenant-Management.md)
### AbpTenants
Esta tabela armazena informações sobre os inquilinos. Cada registro representa um inquilino e contém informações sobre o inquilino, como nome e outros detalhes.
### AbpTenantConnectionStrings
Esta tabela armazena informações sobre as strings de conexão do banco de dados do inquilino. Quando você define uma string de conexão para um inquilino, um novo registro será adicionado a esta tabela. Você pode consultar este banco de dados para obter strings de conexão por inquilinos.
#### Chaves Estrangeiras
| Tabela | Coluna | Descrição |
| --- | --- | --- |
| [AbpTenants](#abptenants) | Id | A coluna `Id` na tabela `AbpTenants` é usada para associar a string de conexão do inquilino ao inquilino correspondente. |
## Módulo de Blogging
### BlgUsers
Esta tabela armazena informações sobre os usuários do blog. Quando um novo usuário de identidade é criado, um novo registro será adicionado a esta tabela.
### BlgBlogs
Esta tabela serve para armazenar informações do blog e separar semanticamente as postagens de cada blog.
### BlgPosts
Esta tabela armazena informações sobre as postagens do blog. Você pode consultar esta tabela para obter postagens de blog por blogs.
#### Chaves Estrangeiras
| Tabela | Coluna | Descrição |
| --- | --- | --- |
| [BlgBlogs](#blgblogs) | Id | Para associar a postagem do blog ao blog correspondente. |
### BlgComments
Esta tabela armazena informações sobre os comentários feitos nas postagens do blog. Você pode consultar esta tabela para obter comentários por postagens.
#### Chaves Estrangeiras
| Tabela | Coluna | Descrição |
| --- | --- | --- |
| [BlgPosts](#blgposts) | Id | Vincula o comentário à postagem do blog correspondente. |
| [BlgComments](#blgcomments) | Id | Vincula o comentário ao comentário pai. |
### BlgTags
Esta tabela armazena informações sobre as tags. Quando uma nova tag é usada, um novo registro será adicionado a esta tabela. Você pode consultar esta tabela para obter tags por blogs.
### BlgPostTags
Esta tabela é usada para associar tags a postagens de blog, a fim de categorizar e organizar o conteúdo. Você pode consultar esta tabela para obter tags de postagens por postagens.
#### Chaves Estrangeiras
| Tabela | Coluna | Descrição |
| --- | --- | --- |
| [BlgTags](#blgtags) | Id | Vincula a tag da postagem à tag correspondente. |
| [BlgPosts](#blgposts) | Id | Vincula a tag da postagem à postagem do blog correspondente. |
## [Módulo CMS Kit](Cms-Kit/Index.md)
### CmsUsers
Esta tabela armazena informações sobre os usuários do módulo CMS Kit. Quando um novo usuário de identidade é criado, um novo registro será adicionado a esta tabela.
### CmsBlogs
Esta tabela serve para armazenar informações do blog e separar semanticamente as postagens de cada blog.
### CmsBlogPosts
Esta tabela armazena informações sobre as postagens do blog. Você pode consultar esta tabela para obter postagens de blog por blogs.
#### Chaves Estrangeiras
| Tabela | Coluna | Descrição |
| --- | --- | --- |
| [CmsUsers](#cmsusers) | Id | Vincula a postagem do blog ao autor correspondente. |
### CmsBlogFeatures
Esta tabela armazena informações sobre os recursos do blog. Você pode consultar esta tabela para obter recursos do blog por blogs.
### CmsComments
Esta tabela é utilizada pelo sistema de comentários do CMS Kit para armazenar comentários feitos nas postagens do blog. Você pode consultar esta tabela para obter comentários por postagens.
### CmsTags
Esta tabela armazena informações sobre as tags. Quando uma nova tag é usada, um novo registro será adicionado a esta tabela. Você pode consultar esta tabela para obter tags por blogs.
### CmsEntityTags
Esta tabela é utilizada pelo sistema de gerenciamento de tags para armazenar tags e sua relação com várias entidades, permitindo assim a categorização e organização eficiente do conteúdo. Você pode consultar esta tabela para obter tags de entidades por entidades.
### CmsGlobalResources
Esta tabela é uma tabela de banco de dados para o sistema de recursos globais do CMS Kit, permitindo a adição dinâmica de estilos e scripts globais.
### CmsMediaDescriptors
Esta tabela é utilizada pelo módulo CMS Kit para gerenciar arquivos de mídia usando o módulo [BlobStoring](../Blob-Storing.md).
### CmsMenuItems
Esta tabela é usada pelo sistema de menu do CMS Kit para gerenciar e armazenar informações sobre menus públicos dinâmicos, incluindo detalhes como nomes de exibição de itens de menu, URLs e relacionamentos hierárquicos.
### CmsPages
Esta tabela é utilizada pelo sistema de páginas do CMS Kit para armazenar páginas dinâmicas dentro do aplicativo, incluindo informações como URLs de página, títulos e conteúdo.
### CmsRatings
Esta tabela é utilizada pelo sistema de classificação do CMS Kit para armazenar classificações feitas em postagens de blog. Você pode consultar esta tabela para obter classificações por postagens.
### CmsUserReactions
Esta tabela é utilizada pelo sistema de reações do CMS Kit para armazenar reações feitas em postagens de blog. Você pode consultar esta tabela para obter reações por postagens.
## [Módulo de Documentação](Docs.md)
### DocsProjects
Esta tabela armazena informações do projeto para categorizar documentos de acordo com diferentes projetos.
### DocsDocuments
Esta tabela recupera o documento se ele não for encontrado no cache. A documentação está sendo atualizada quando o conteúdo é recuperado do banco de dados.
### DocsDocumentContributors
Esta tabela armazena informações sobre os contribuidores dos documentos. Você pode consultar esta tabela para obter contribuidores de documentos por documentos.
#### Chaves Estrangeiras
| Tabela | Coluna | Descrição |
| --- | --- | --- |
| [DocsDocuments](#docsdocuments) | Id | Vincula o contribuidor do documento ao documento correspondente. |
## [Módulo de Gerenciamento de Recursos](Feature-Management.md)
### AbpFeatureGroups
Esta tabela armazena informações sobre os grupos de recursos no aplicativo. Por exemplo, você pode agrupar todos os recursos na tabela [`AbpFeatures`](#abpfeatures) relacionados ao módulo `Identity` sob o grupo `Identity`.
### AbpFeatures
Esta tabela armazena informações sobre os recursos no aplicativo. Você pode usar a coluna `Name` para vincular cada recurso com seu valor de recurso correspondente na tabela [`AbpFeatureValues`](#abpfeaturevalues), para que você possa gerenciar e organizar facilmente os recursos.
### AbpFeatureValues
Esta tabela armazena os valores dos recursos para diferentes provedores. Você pode usar a coluna `Name` para vincular cada valor de recurso com seu recurso correspondente na tabela [`AbpFeatures`](#abpfeatures), para que você possa gerenciar e organizar facilmente os recursos.
## [Módulo de Identidade](Identity.md)
### AbpUsers
Esta tabela armazena informações sobre os usuários de identidade no aplicativo.
### AbpRoles
Esta tabela armazena informações sobre os papéis no aplicativo. Os papéis são usados para gerenciar e controlar o acesso a diferentes partes do aplicativo, atribuindo permissões e reivindicações aos papéis e, em seguida, atribuindo esses papéis aos usuários. Esta tabela é importante para gerenciar e organizar os papéis no aplicativo e para definir os direitos de acesso dos usuários.
### AbpClaimTypes
Esta tabela armazena informações sobre os tipos de reivindicação usados no aplicativo. Você pode usar as colunas `Name` e `Regex` para filtrar os tipos de reivindicação por nome e padrão regex, respectivamente, para que você possa gerenciar e rastrear facilmente os tipos de reivindicação no aplicativo.
### AbpLinkUsers
Esta tabela é útil para vincular várias contas de usuário em diferentes inquilinos ou aplicativos a um único usuário, permitindo que eles alternem facilmente entre suas contas.
### AbpUserClaims
Esta tabela pode gerenciar o controle de acesso baseado em usuário, permitindo atribuir reivindicações aos usuários, que descrevem os direitos de acesso do usuário individual.
#### Chaves Estrangeiras
| Tabela | Coluna | Descrição |
| --- | --- | --- |
| [AbpUsers](#abpusers) | Id | Vincula a reivindicação do usuário ao usuário correspondente. |
### AbpUserLogins
Esta tabela pode armazenar informações sobre os logins externos do usuário, como login com Facebook, Google, etc., e também pode ser usada para rastrear o histórico de login dos usuários.
#### Chaves Estrangeiras
| Tabela | Coluna | Descrição |
| --- | --- | --- |
| [AbpUsers](#abpusers) | Id | Vincula o login do usuário ao usuário correspondente. |
### AbpUserRoles
Esta tabela pode gerenciar o controle de acesso baseado em usuário, permitindo atribuir papéis aos usuários, que descrevem os direitos de acesso do usuário individual.
#### Chaves Estrangeiras
| Tabela | Coluna | Descrição |
| --- | --- | --- |
| [AbpUsers](#abpusers) | Id | Vincula o papel do usuário ao usuário correspondente. |
| [AbpRoles](#abproles) | Id | Vincula o papel do usuário ao papel correspondente. |
### AbpUserTokens
Esta tabela pode armazenar informações sobre tokens de atualização, tokens de acesso e outros tokens usados no aplicativo. Também pode ser usado para invalidar ou revogar tokens de usuário.
#### Chaves Estrangeiras
| Tabela | Coluna | Descrição |
| --- | --- | --- |
| [AbpUsers](#abpusers) | Id | Vincula o token do usuário ao usuário correspondente. |
### AbpOrganizationUnits
Esta tabela é útil para criar e gerenciar uma estrutura hierárquica da organização, permitindo agrupar usuários e atribuir papéis com base na estrutura da organização. Você pode usar as colunas `Code` e `ParentId` para filtrar as unidades organizacionais por código e ID do pai, respectivamente, para que você possa gerenciar e rastrear facilmente as unidades organizacionais no aplicativo.
#### Chaves Estrangeiras
| Tabela | Coluna | Descrição |
| --- | --- | --- |
| [AbpOrganizationUnits](#abporganizationunits) | ParentId | Vincula a unidade organizacional à sua unidade organizacional pai. |
### AbpOrganizationUnitRoles
Esta tabela é útil para gerenciar o controle de acesso baseado em função no nível das unidades organizacionais, permitindo atribuir diferentes papéis a diferentes partes da estrutura da organização. Você pode usar as colunas `OrganizationUnitId` e `RoleId` para filtrar os papéis por ID da unidade organizacional e ID do papel, respectivamente, para que você possa gerenciar e rastrear facilmente os papéis atribuídos às unidades organizacionais no aplicativo.
#### Chaves Estrangeiras
| Tabela | Coluna | Descrição |
| --- | --- | --- |
| [AbpOrganizationUnits](#abporganizationunits) | Id | Vincula o papel da unidade organizacional à unidade organizacional correspondente. |
| [AbpRoles](#abproles) | Id | Vincula o papel da unidade organizacional ao papel correspondente. |
### AbpUserOrganizationUnits
Esta tabela armazena informações sobre as unidades organizacionais atribuídas aos usuários no aplicativo. Esta tabela pode gerenciar relacionamentos entre usuário e unidade organizacional e agrupar usuários com base na estrutura da organização.
#### Chaves Estrangeiras
| Tabela | Coluna | Descrição |
| --- | --- | --- |
| [AbpUsers](#abpusers) | Id | Vincula a unidade organizacional do usuário ao usuário correspondente. |
| [AbpOrganizationUnits](#abporganizationunits) | Id | Vincula a unidade organizacional do usuário à unidade organizacional correspondente. |
### AbpRoleClaims
Esta tabela é útil para gerenciar o controle de acesso baseado em função, permitindo atribuir reivindicações aos papéis, que descrevem os direitos de acesso dos usuários que pertencem a esse papel.
#### Chaves Estrangeiras
| Tabela | Coluna | Descrição |
| --- | --- | --- |
| [AbpRoles](#abproles) | Id | Vincula a reivindicação do papel ao papel correspondente. |
### AbpSecurityLogs
Esta tabela registra operações e alterações importantes relacionadas às contas de usuário, permitindo que os usuários salvem os logs de segurança para referência futura.
## [Gerenciamento de Permissões](Permission-Management.md)
### AbpPermissionGroups
Esta tabela é importante para gerenciar e organizar as permissões no aplicativo, agrupando-as em categorias lógicas.
### AbpPermissions
Esta tabela é importante para gerenciar e controlar o acesso a diferentes partes do aplicativo e para definir as permissões granulares que compõem as permissões ou papéis maiores.
### AbpPermissionGrants
A tabela armazena e gerencia as permissões no aplicativo e mantém o controle das permissões concedidas, para quem e quando. Colunas como `Name`, `ProviderName`, `ProviderKey`, `TenantId` podem ser usadas para filtrar as permissões concedidas por nome, nome do provedor, chave do provedor e ID do inquilino, respectivamente, para que você possa gerenciar e rastrear facilmente as permissões concedidas no aplicativo.
## [Gerenciamento de Configurações](Setting-Management.md)
### AbpSettings
Esta tabela armazena pares de chave-valor de configurações para o aplicativo e permite a configuração dinâmica do aplicativo sem a necessidade de recompilação.
## [OpenIddict](OpenIddict.md)
### OpenIddictApplications
Esta tabela pode armazenar informações sobre as aplicações OpenID Connect, incluindo o ID do cliente, segredo do cliente, URI de redirecionamento e outras informações relevantes. Também pode ser usado para autenticar e autorizar clientes usando o protocolo OpenID Connect.
### OpenIddictAuthorizations
Esta tabela armazena os dados de autorização do OpenID Connect no aplicativo. Também pode ser usado para gerenciar e validar as concessões de autorização emitidas para clientes e usuários.
#### Chaves Estrangeiras
| Tabela | Coluna | Descrição |
| --- | --- | --- |
| [OpenIddictApplications](#openiddictapplications) | Id | Vincula a autorização à aplicação correspondente. |
### OpenIddictTokens
Esta tabela pode armazenar informações sobre os tokens OpenID Connect, incluindo o payload do token, expiração, tipo e outras informações relevantes. Também pode ser usado para gerenciar e validar os tokens emitidos para clientes e usuários, como tokens de acesso e tokens de atualização, e controlar o acesso a recursos protegidos.
#### Chaves Estrangeiras
| Tabela | Coluna | Descrição |
| --- | --- | --- |
| [OpenIddictApplications](#openiddictapplications) | Id | Vincula o token à aplicação correspondente. |
| [OpenIddictAuthorizations](#openiddictauthorizations) | Id | Vincula o token à autorização correspondente. |
### OpenIddictScopes
Esta tabela pode armazenar informações sobre os escopos OpenID Connect, incluindo o nome e a descrição do escopo. Também pode ser usado para definir as permissões ou direitos de acesso associados aos escopos, que são então usados para controlar o acesso a recursos protegidos.
## [IdentityServer](IdentityServer.md)
### IdentityServerApiResources
Esta tabela pode armazenar informações sobre os recursos da API, incluindo o nome do recurso, nome de exibição, descrição e outras informações relevantes. Também pode ser usado para definir os escopos, reivindicações e propriedades associadas aos recursos da API, que são então usados para controlar o acesso a recursos protegidos.
### IdentityServerIdentityResources
Esta tabela pode armazenar informações sobre os recursos de identidade, incluindo o nome, nome de exibição, descrição e status habilitado.
### IdentityServerClients
Esta tabela pode armazenar informações sobre os clientes, incluindo o ID do cliente, nome do cliente, URI do cliente e outras informações relevantes. Também pode ser usado para definir os escopos, reivindicações e propriedades associadas aos clientes, que são então usados para controlar o acesso a recursos protegidos.
### IdentityServerApiScopes
Esta tabela pode armazenar informações sobre os escopos da API, incluindo o nome do escopo, nome de exibição, descrição e outras informações relevantes. Também pode ser usado para definir as reivindicações e propriedades associadas aos escopos da API, que são então usados para controlar o acesso a recursos protegidos.
### IdentityServerApiResourceClaims
Esta tabela pode armazenar informações sobre as reivindicações de um recurso da API, incluindo o tipo de reivindicação e o ID do recurso da API.
#### Chaves Estrangeiras
| Tabela | Coluna | Descrição |
| --- | --- | --- |
| [IdentityServerApiResources](#identityserverapiresources) | Id | Vincula a reivindicação ao recurso da API correspondente. |
### IdentityServerIdentityResourceClaims
Esta tabela pode armazenar informações sobre as reivindicações de um recurso de identidade, incluindo o tipo de reivindicação e o ID do recurso de identidade.
#### Chaves Estrangeiras
| Tabela | Coluna | Descrição |
| --- | --- | --- |
| [IdentityServerIdentityResources](#identityserveridentityresources) | Id | Vincula a reivindicação ao recurso de identidade correspondente. |
### IdentityServerClientClaims
Esta tabela pode armazenar informações sobre as reivindicações de um cliente, incluindo o tipo de reivindicação, valor da reivindicação e ID do cliente.
#### Chaves Estrangeiras
| Tabela | Coluna | Descrição |
| --- | --- | --- |
| [IdentityServerClients](#identityserverclients) | Id | Vincula a reivindicação ao cliente correspondente. |
### IdentityServerApiScopeClaims
Esta tabela pode armazenar informações sobre as reivindicações de um escopo da API, incluindo o tipo de reivindicação e o ID do escopo da API.
#### Chaves Estrangeiras
| Tabela | Coluna | Descrição |
| --- | --- | --- |
| [IdentityServerApiScopes](#identityserverapiscopes) | Id | Vincula a reivindicação ao escopo da API correspondente. |
### IdentityServerApiResourceProperties
Esta tabela pode armazenar informações sobre propriedades, incluindo a chave da propriedade e o valor, e o recurso da API associado. Essas propriedades podem armazenar metadados adicionais ou informações de configuração relacionadas aos recursos da API.
#### Chaves Estrangeiras
| Tabela | Coluna | Descrição |
| --- | --- | --- |
| [IdentityServerApiResources](#identityserverapiresources) | Id | Vincula a propriedade ao recurso da API correspondente. |
### IdentityServerIdentityResourceProperties
Esta tabela pode armazenar informações sobre propriedades, incluindo a chave da propriedade e o valor, e o recurso de identidade associado. Essas propriedades podem armazenar metadados adicionais ou informações de configuração relacionadas aos recursos de identidade.
#### Chaves Estrangeiras
| Tabela | Coluna | Descrição |
| --- | --- | --- |
| [IdentityServerIdentityResources](#identityserveridentityresources) | Id | Vincula a propriedade ao recurso de identidade correspondente. |
### IdentityServerClientProperties
Esta tabela pode armazenar informações sobre as propriedades de um cliente, incluindo a chave, valor e ID do cliente. Essas propriedades podem armazenar metadados adicionais ou informações de configuração relacionadas aos clientes.
#### Chaves Estrangeiras
| Tabela | Coluna | Descrição |
| --- | --- | --- |
| [IdentityServerClients](#identityserverclients) | Id | Vincula a propriedade ao cliente correspondente. |
### IdentityServerApiScopeProperties
Esta tabela pode armazenar informações sobre as propriedades de um escopo da API, incluindo a chave, valor e ID do escopo da API. Essas propriedades podem armazenar metadados adicionais ou informações de configuração relacionadas aos escopos da API.
#### Chaves Estrangeiras
| Tabela | Coluna | Descrição |
| --- | --- | --- |
| [IdentityServerApiScopes](#identityserverapiscopes) | Id | Vincula a propriedade ao escopo da API correspondente. |
### IdentityServerApiResourceScopes
Esta tabela pode armazenar informações sobre os escopos de um recurso da API, incluindo o nome do escopo e o ID do recurso da API.
#### Chaves Estrangeiras
| Tabela | Coluna | Descrição |
| --- | --- | --- |
| [IdentityServerApiResources](#identityserverapiresources) | Id | Vincula o escopo ao recurso da API correspondente. |
### IdentityServerClientScopes
Esta tabela pode armazenar informações sobre os escopos de um cliente, incluindo o escopo e o ID do cliente.
#### Chaves Estrangeiras
| Tabela | Coluna | Descrição |
| --- | --- | --- |
| [IdentityServerClients](#identityserverclients) | Id | Vincula o escopo ao cliente correspondente. |
### IdentityServerApiResourceSecrets
Esta tabela pode armazenar informações sobre os segredos de um recurso da API, incluindo o valor do segredo, data de expiração e ID do recurso da API.
#### Chaves Estrangeiras
| Tabela | Coluna | Descrição |
| --- | --- | --- |
| [IdentityServerApiResources](#identityserverapiresources) | Id | Vincula o segredo ao recurso da API correspondente. |
### IdentityServerClientSecrets
Esta tabela pode armazenar informações sobre os segredos de um cliente, incluindo o valor do segredo, data de expiração e ID do cliente.
#### Chaves Estrangeiras
| Tabela | Coluna | Descrição |
| --- | --- | --- |
| [IdentityServerClients](#identityserverclients) | Id | Vincula o segredo ao cliente correspondente. |
### IdentityServerClientCorsOrigins
Esta tabela pode armazenar informações sobre as origens CORS de um cliente, incluindo a origem e o ID do cliente. Também pode ser usado para gerenciar e validar as origens CORS de um cliente.
#### Chaves Estrangeiras
| Tabela | Coluna | Descrição |
| --- | --- | --- |
| [IdentityServerClients](#identityserverclients) | Id | Vincula a origem CORS ao cliente correspondente. |
### IdentityServerClientGrantTypes
Esta tabela pode armazenar informações sobre os tipos de concessão de um cliente, incluindo o tipo de concessão e o ID do cliente.
#### Chaves Estrangeiras
| Tabela | Coluna | Descrição |
| --- | --- | --- |
| [IdentityServerClients](#identityserverclients) | Id | Vincula o tipo de concessão ao cliente correspondente. |
### IdentityServerClientIdPRestrictions
Esta tabela pode armazenar informações sobre as restrições do provedor de identidade de um cliente, incluindo o provedor de identidade e o ID do cliente.
#### Chaves Estrangeiras
| Tabela | Coluna | Descrição |
| --- | --- | --- |
| [IdentityServerClients](#identityserverclients) | Id | Vincula a restrição do provedor de identidade ao cliente correspondente. |
### IdentityServerClientPostLogoutRedirectUris
Esta tabela pode armazenar informações sobre os URIs de redirecionamento pós logout de um cliente, incluindo o URI de redirecionamento pós logout e o ID do cliente.
#### Chaves Estrangeiras
| Tabela | Coluna | Descrição |
| --- | --- | --- |
| [IdentityServerClients](#identityserverclients) | Id | Vincula o URI de redirecionamento pós logout ao cliente correspondente. |
### IdentityServerClientRedirectUris
Esta tabela pode armazenar informações sobre os URIs de redirecionamento de um cliente, incluindo o URI de redirecionamento e o ID do cliente.
#### Chaves Estrangeiras
| Tabela | Coluna | Descrição |
| --- | --- | --- |
| [IdentityServerClients](#identityserverclients) | Id | Vincula o URI de redirecionamento ao cliente correspondente. |
### IdentityServerDeviceFlowCodes
Esta tabela pode armazenar informações sobre os códigos de fluxo de dispositivo, incluindo o código do usuário, código do dispositivo, ID do assunto, ID do cliente, data de criação, expiração, dados e ID da sessão.
### IdentityServerPersistedGrants
Esta tabela pode armazenar informações sobre as concessões persistidas, incluindo a chave, tipo, ID do assunto, ID do cliente, data de criação, expiração e dados.
## Outros
### AbpBlobContainers
Esta tabela é importante para fornecer uma melhor experiência do usuário, permitindo que o aplicativo suporte vários contêineres e forneça recursos específicos de BLOB.
### AbpBlobs
Esta tabela armazena os dados binários de BLOBs (objetos binários grandes) no aplicativo. Cada BLOB está relacionado a um contêiner na tabela [AbpBlobContainers](#abpblobcontainers), onde o nome do contêiner, ID do inquilino e outras propriedades do contêiner podem ser encontrados.
#### Chaves Estrangeiras
| Tabela | Coluna | Descrição |
| --- | --- | --- |
| [AbpBlobContainers](#abpblobcontainers) | Id | Vincula o BLOB ao contêiner correspondente. |
### AbpLocalizationResources
Esta tabela armazena os recursos de localização para o aplicativo. Esta tabela é importante para fornecer uma melhor experiência do usuário, permitindo que o aplicativo suporte vários recursos e forneça texto localizado e outros recursos específicos de localização.
### AbpLocalizationTexts
A tabela contém o nome do recurso, nome da cultura e um valor codificado em JSON que contém o par chave-valor do texto de localização. Ele permite o armazenamento e gerenciamento eficiente de textos de localização e permite a atualização fácil ou adição de novas traduções para recursos e culturas específicas.

675
docs/pt-BR/Modules/Docs.md

@ -0,0 +1,675 @@
# Módulo de Documentação
## O que é o Módulo de Documentação?
O módulo de documentação é um módulo de aplicação para o framework ABP. Ele simplifica a documentação de software. Este módulo é gratuito e de código aberto.
### Integração
Atualmente, o módulo de documentação permite que você armazene sua documentação tanto no GitHub quanto no sistema de arquivos.
### Hospedagem
O módulo de documentação é um módulo de aplicação e não oferece nenhuma solução de hospedagem. Você pode hospedar sua documentação localmente ou na nuvem.
### Versionamento
Quando você usa o GitHub para armazenar sua documentação, o módulo de documentação suporta o versionamento. Se você tiver várias versões para sua documentação, haverá uma caixa de seleção na interface do usuário para alternar entre as versões. Se você escolher o sistema de arquivos para armazenar sua documentação, ele não suportará várias versões.
[Os documentos](https://docs.abp.io/) para o framework ABP também estão usando este módulo.
> O módulo de documentação segue as melhores práticas de arquitetura de módulos.
## Instalação
Este documento aborda o provedor `Entity Framework Core`, mas você também pode selecionar o `MongoDB` como seu provedor de banco de dados.
### 1- Criando uma aplicação
Se você não tiver um projeto ABP existente, você pode gerar um comando CLI a partir da página de início do site abp.io e executá-lo ou executar o comando abaixo:
```bash
abp new Acme.MyProject
```
### 2- Executando a aplicação vazia
Após baixar o projeto, extraia o arquivo ZIP e abra `Acme.MyProject.sln`. Você verá que a solução consiste nos projetos `Application`, `Application.Contracts`, `DbMigrator`, `Domain`, `Domain.Shared`, `EntityFrameworkCore`, `HttpApi`, `HttpApi.Client` e `Web`. Clique com o botão direito no projeto `Acme.MyProject.Web` e selecione **Definir como Projeto de Inicialização**.
![Criar um novo projeto](../images/docs-module_solution-explorer.png)
A string de conexão do banco de dados está localizada em `appsettings.json` do seu projeto `Acme.MyProject.Web`. Se você tiver uma configuração de banco de dados diferente, altere a string de conexão.
```json
{
"ConnectionStrings": {
"Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=MyProject;Trusted_Connection=True"
}
}
```
Execute o projeto `Acme.MyProject.DbMigrator`, ele será responsável por aplicar a migração do banco de dados e os dados iniciais. O banco de dados `MyProject` será criado em seu servidor de banco de dados.
Agora um projeto ABP vazio foi criado! Agora você pode executar seu projeto e ver o site vazio.
Para fazer login no seu site, digite `admin` como nome de usuário e `1q2w3E*` como senha.
### 3- Instalação do Módulo
Os pacotes do módulo de documentação estão hospedados no NuGet. Existem 4 pacotes que precisam ser instalados em sua aplicação. Cada pacote deve ser instalado no projeto relevante.
#### 3.1- Usando o ABP CLI
É recomendado usar o ABP CLI para instalar o módulo. Abra a janela do CMD no diretório do arquivo de solução (`.sln`) e execute o seguinte comando:
```bash
abp add-module Volo.Docs
```
#### 3.2- Instalação manual
Ou você também pode instalar manualmente o pacote NuGet em cada projeto:
* Instale o pacote NuGet [Volo.Docs.Domain](https://www.nuget.org/packages/Volo.Docs.Domain/) no projeto `Acme.MyProject.Domain`.
```bash
Install-Package Volo.Docs.Domain
```
* Instale o pacote NuGet [Volo.Docs.EntityFrameworkCore](https://www.nuget.org/packages/Volo.Docs.EntityFrameworkCore/) no projeto `Acme.MyProject.EntityFrameworkCore`.
```bash
Install-Package Volo.Docs.EntityFrameworkCore
```
* Instale o pacote NuGet [Volo.Docs.Application](https://www.nuget.org/packages/Volo.Docs.Application/) no projeto `Acme.MyProject.Application`.
```bash
Install-Package Volo.Docs.Application
```
* Instale o pacote NuGet [Volo.Docs.Web](https://www.nuget.org/packages/Volo.Docs.Domain/) no projeto `Acme.MyProject.Web`.
```bash
Install-Package Volo.Docs.Web
```
##### 3.2.1- Adicionando Dependências de Módulo
Um módulo ABP deve declarar o atributo `[DependsOn]` se tiver uma dependência de outro módulo. Cada módulo deve ser adicionado no atributo `[DependsOn]` do projeto relevante.
* Abra `MyProjectDomainModule.cs` e adicione `typeof(DocsDomainModule)` como mostrado abaixo;
```csharp
[DependsOn(
typeof(DocsDomainModule),
typeof(AbpIdentityDomainModule),
typeof(AbpAuditingModule),
typeof(BackgroundJobsDomainModule),
typeof(AbpAuditLoggingDomainModule)
)]
public class MyProjectDomainModule : AbpModule
{
//...
}
```
* Abra `MyProjectEntityFrameworkCoreModule.cs` e adicione `typeof(DocsEntityFrameworkCoreModule)` como mostrado abaixo;
```csharp
[DependsOn(
typeof(DocsEntityFrameworkCoreModule),
typeof(MyProjectDomainModule),
typeof(AbpIdentityEntityFrameworkCoreModule),
typeof(AbpPermissionManagementEntityFrameworkCoreModule),
typeof(AbpSettingManagementEntityFrameworkCoreModule),
typeof(AbpEntityFrameworkCoreSqlServerModule),
typeof(BackgroundJobsEntityFrameworkCoreModule),
typeof(AbpAuditLoggingEntityFrameworkCoreModule)
)]
public class MyProjectEntityFrameworkCoreModule : AbpModule
{
//...
}
```
* Abra `MyProjectApplicationModule.cs` e adicione `typeof(DocsApplicationModule)` como mostrado abaixo;
```csharp
[DependsOn(
typeof(DocsApplicationModule),
typeof(MyProjectDomainModule),
typeof(AbpIdentityApplicationModule))]
public class MyProjectApplicationModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpPermissionOptions>(options =>
{
options.DefinitionProviders.Add<MyProjectPermissionDefinitionProvider>();
});
Configure<AbpAutoMapperOptions>(options =>
{
options.AddProfile<MyProjectApplicationAutoMapperProfile>();
});
}
}
```
* Abra `MyProjectWebModule.cs` e adicione `typeof(DocsWebModule)` como mostrado abaixo;
```csharp
[DependsOn(
typeof(DocsWebModule),
typeof(MyProjectApplicationModule),
typeof(MyProjectEntityFrameworkCoreModule),
typeof(AbpAutofacModule),
typeof(AbpIdentityWebModule),
typeof(AbpAccountWebModule),
typeof(AbpAspNetCoreMvcUiBasicThemeModule)
)]
public class MyProjectWebModule : AbpModule
{
//...
}
```
##### 3.2.2- Adicionando Pacote NPM
Abra `package.json` e adicione `@abp/docs": "^5.0.0` como mostrado abaixo:
```json
{
"version": "1.0.0",
"name": "my-app",
"private": true,
"dependencies": {
"@abp/aspnetcore.mvc.ui.theme.basic": "^5.0.0",
"@abp/docs": "^5.0.0"
}
}
```
Em seguida, abra o terminal de linha de comando na pasta do projeto `Acme.MyProject.Web` e execute o seguinte comando:
````bash
abp install-libs
````
### 4- Integração com o Banco de Dados
#### 4.1- Integração com o Entity Framework
Se você escolher o Entity Framework como seu provedor de banco de dados, precisará configurar o módulo de documentação. Para fazer isso;
- Abra `MyProjectMigrationsDbContext.cs` e adicione `builder.ConfigureDocs()` ao `OnModelCreating()`.
```csharp
public class MyProjectMigrationsDbContext : AbpDbContext<MyProjectMigrationsDbContext>
{
public MyProjectMigrationsDbContext(DbContextOptions<MyProjectMigrationsDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
/* Inclua módulos no contexto de migração do banco de dados */
builder.ConfigurePermissionManagement();
builder.ConfigureSettingManagement();
builder.ConfigureBackgroundJobs();
builder.ConfigureAuditLogging();
builder.ConfigureIdentity();
builder.ConfigureIdentityServer();
builder.ConfigureFeatureManagement();
builder.ConfigureTenantManagement();
builder.ConfigureDocs(); //Adicione esta linha para configurar o módulo de documentação
/* Configure personalizações para entidades dos módulos incluídos */
builder.Entity<IdentityUser>(b =>
{
b.ConfigureCustomUserProperties();
});
/* Configure suas próprias tabelas/entidades dentro do método ConfigureMyProject */
builder.ConfigureMyProject();
}
}
```
* Abra o `Console do Gerenciador de Pacotes` no `Visual Studio` e escolha `Acme.MyProject.EntityFrameworkCore` como projeto padrão. Em seguida, escreva o comando abaixo para adicionar a migração para o módulo de documentação.
```csharp
add-migration Added_Docs_Module
```
Quando o comando for executado com sucesso, você verá um novo arquivo de migração chamado `20181221111621_Added_Docs_Module` na pasta `Acme.MyProject.EntityFrameworkCore\Migrations`.
Agora, atualize o banco de dados para as alterações do módulo de documentação. Para fazer isso, execute o código abaixo no `Console do Gerenciador de Pacotes` no `Visual Studio`. Certifique-se de que `Acme.MyProject.EntityFrameworkCore` ainda é o projeto padrão.
```csharp
update-database
```
Por fim, você pode verificar seu banco de dados para ver as tabelas recém-criadas. Por exemplo, você pode ver a tabela `DocsProjects` adicionada ao seu banco de dados.
### 5- Vinculando o Módulo de Documentação
A rota padrão para o módulo de documentação é;
```txt
/Documents
```
Para adicionar o link do módulo de documentação ao menu de sua aplicação;
* Abra `MyProjectMenuContributor.cs` e adicione a linha abaixo ao método `ConfigureMainMenuAsync()`.
```csharp
context.Menu.Items.Add(new ApplicationMenuItem("MyProject.Docs", l["Menu:Docs"], "/Documents"));
```
A aparência final de **MyProjectMenuContributor.cs**
```csharp
private async Task ConfigureMainMenuAsync(MenuConfigurationContext context)
{
var l = context.ServiceProvider.GetRequiredService<IStringLocalizer<MyProjectResource>>();
context.Menu.Items.Insert(0, new ApplicationMenuItem("MyProject.Home", l["Menu:Home"], "/"));
context.Menu.Items.Add(new ApplicationMenuItem("MyProject.Docs", l["Menu:Docs"], "/Documents"));
}
```
A palavra-chave `Menu:Docs` é uma chave de localização. Para localizar o texto do menu, abra `Localization\MyProject\en.json` no projeto `Acme.MyProject.Domain`. E adicione a linha abaixo
```json
"Menu:Docs": "Documentos"
```
A aparência final de **en.json**
```json
{
"culture": "en",
"texts": {
"Menu:Home": "Início",
"Welcome": "Bem-vindo",
"LongWelcomeMessage": "Bem-vindo à aplicação. Este é um projeto inicial baseado no framework ABP. Para obter mais informações, visite abp.io.",
"Menu:Docs": "Documentos"
}
}
```
O novo item de menu para o Módulo de Documentação foi adicionado ao menu. Execute sua aplicação web e acesse a URL `http://localhost:YOUR_PORT_NUMBER/documents`.
Você verá um aviso que diz;
```txt
Ainda não há projetos!
```
Como ainda não adicionamos nenhum projeto, este aviso é normal.
### 6- Adicionando um Novo Projeto de Documentação
Abra `DocsProjects` em seu banco de dados e insira um novo registro com as seguintes informações de campo;
* **Name**: O nome de exibição do nome do documento que será mostrado na página da web.
* **ShortName**: Um nome curto e amigável para URL que será usado na URL de seus documentos.
* **Format**: O formato do documento (para Markdown: `md`, para HTML: `html`)
* **DefaultDocumentName**: O documento para a página inicial.
* **NavigationDocumentName**: O documento a ser usado para o menu de navegação (Índice).
* **MinimumVersion**: A versão mínima para mostrar os documentos. As versões abaixo não serão listadas.
* **DocumentStoreType**: A fonte dos documentos (para GitHub:`GitHub`, para sistema de arquivos`FileSystem`)
* **ExtraProperties**: Um JSON serializado que armazena configurações especiais para o `DocumentStoreType` selecionado.
* **MainWebsiteUrl**: A URL para quando o usuário clicar no logotipo da página do módulo de documentação. Você pode simplesmente definir como `/` para vincular ao endereço raiz do seu site.
* **LatestVersionBranchName**: Esta é uma configuração para o GitHub. É o nome do branch que será usado para recuperar os documentos. Você pode definir como `master`.
#### Exemplo de Registro de Projeto para "GitHub"
Você pode usar a documentação do [ABP Framework](https://github.com/abpframework/abp/) no GitHub para configurar seu repositório de documentos do GitHub.
- Name: `ABP framework (GitHub)`
- ShortName: `abp`
- Format: `md`
- DefaultDocumentName: `Index`
- NavigationDocumentName: `docs-nav.json`
- MinimumVersion: `<NULL>` (sem versão mínima)
- DocumentStoreType: `GitHub`
- ExtraProperties:
```json
{"GitHubRootUrl":"https://github.com/abpframework/abp/tree/{version}/docs","GitHubAccessToken":"***","GitHubUserAgent":""}
```
Observe que `GitHubAccessToken` está mascarado com `***`. É um token privado que você deve obter do GitHub. Consulte https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/
- MainWebsiteUrl: `/`
- LatestVersionBranchName: `dev`
Para bancos de dados `SQL`, você pode usar o comando `T-SQL` abaixo para inserir o exemplo especificado em sua tabela `DocsProjects`:
```mssql
INSERT [dbo].[DocsProjects] ([Id], [Name], [ShortName], [Format], [DefaultDocumentName], [NavigationDocumentName], [MinimumVersion], [DocumentStoreType], [ExtraProperties], [MainWebsiteUrl], [LatestVersionBranchName], [ParametersDocumentName], [ConcurrencyStamp]) VALUES (N'12f21123-e08e-4f15-bedb-ae0b2d939659', N'ABP framework (FileSystem)', N'abp', N'md', N'Index', N'docs-nav.json', NULL, N'FileSystem', N'{"Path":"C:\\Github\\abp\\docs"}', N'/', NULL, N'', N'12f21123e08e4f15bedbae0b2d939659')
```
Esteja ciente de que `GitHubAccessToken` está mascarado. É um token privado e você deve obter seu próprio token e substituir a string `***`.
Agora você pode executar a aplicação e navegar até `/Documents`.
#### Exemplo de Registro de Projeto para "FileSystem"
Você pode usar a documentação do [ABP Framework](https://github.com/abpframework/abp/) no GitHub para configurar seu repositório de documentos do GitHub.
- Name: `ABP framework (FileSystem)`
- ShortName: `abp`
- Format: `md`
- DefaultDocumentName: `Index`
- NavigationDocumentName: `docs-nav.json`
- MinimumVersion: `<NULL>` (sem versão mínima)
- DocumentStoreType: `FileSystem`
- ExtraProperties:
```json
{"Path":"C:\\Github\\abp\\docs"}
```
Observe que `Path` deve ser substituído pelo diretório de documentos local. Você pode obter a documentação do ABP Framework em https://github.com/abpframework/abp/tree/master/docs e copiar para o diretório `C:\\Github\\abp\\docs` para que funcione.
- MainWebsiteUrl: `/`
- LatestVersionBranchName: `<NULL>`
Para bancos de dados `SQL`, você pode usar o comando `T-SQL` abaixo para inserir o exemplo especificado em sua tabela `DocsProjects`:
```mssql
INSERT [dbo].[DocsProjects] ([Id], [Name], [ShortName], [Format], [DefaultDocumentName], [NavigationDocumentName], [MinimumVersion], [DocumentStoreType], [ExtraProperties], [MainWebsiteUrl], [LatestVersionBranchName], [ParametersDocumentName]) VALUES (N'12f21123-e08e-4f15-bedb-ae0b2d939659', N'ABP framework (FileSystem)', N'abp', N'md', N'Index', N'docs-nav.json', NULL, N'FileSystem', N'{"Path":"C:\\Github\\abp\\docs"}', N'/', NULL, N'')
```
Adicione um dos projetos de exemplo acima e execute a aplicação. No menu, você verá o link `Documentos`, clique no link do menu para abrir a página de documentos.
Até agora, criamos um novo aplicativo a partir do site abp.io e o preparamos para o módulo de documentação.
### 7- Criando um Novo Documento
No exemplo de registros de projeto, você vê que o `Format` é especificado como `md`, que se refere ao [Mark Down](https://en.wikipedia.org/wiki/Markdown). Você pode ver o guia de referência do mark down seguindo o link abaixo;
https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet
O módulo de documentação do ABP pode renderizar mark down para HTML.
Agora vamos dar uma olhada em um exemplo de documento em formato mark down.
~~~markdown
# Este é um cabeçalho
Bem-vindo ao Módulo de Documentação.
## Este é um subcabeçalho
[Este é um link](https://abp.io)
![Esta é uma imagem](https://abp.io/assets/my-image.png)
## Este é um bloco de código
```csharp
public class Person
{
public string Name { get; set; }
public string Address { get; set; }
}
```
~~~
Como exemplo, você pode ver a documentação do ABP Framework:
[https://github.com/abpframework/abp/blob/master/docs/en/](https://github.com/abpframework/abp/blob/master/docs/en/)
#### Recurso de seções condicionais (Usando Scriban)
O módulo de documentação usa o [Scriban](https://github.com/lunet-io/scriban/tree/master/doc) para mostrar ou ocultar algumas partes de um documento de forma condicional. Para usar esse recurso, você deve criar um arquivo JSON como **documento de parâmetros** para cada idioma. Ele conterá todas as chaves-valores, bem como seus nomes de exibição.
Por exemplo, [en/docs-params.json](https://github.com/abpio/abp-commercial-docs/blob/master/en/docs-params.json):
```json
{
"parameters": [{
"name": "UI",
"displayName": "UI",
"values": {
"MVC": "MVC / Razor Pages",
"NG": "Angular"
}
},
{
"name": "DB",
"displayName": "Database",
"values": {
"EF": "Entity Framework Core",
"Mongo": "MongoDB"
}
},
{
"name": "Tiered",
"displayName": "Tiered",
"values": {
"No": "Not Tiered",
"Yes": "Tiered"
}
}]
}
```
Como nem todos os documentos de seus projetos podem ter seções ou precisar de todos esses parâmetros, você deve declarar quais desses parâmetros serão usados para dividir o documento, como um bloco JSON em qualquer lugar do documento.
Por exemplo [Getting-Started.md](https://github.com/abpio/abp-commercial-docs/blob/master/en/getting-started.md):
```
.....
​```json
//[doc-params]
{
"UI": ["MVC","NG"],
"DB": ["EF", "Mongo"],
"Tiered": ["Yes", "No"]
}
​```
........
```
Esta seção será excluída automaticamente durante a renderização. E, é claro, essas chaves de valores devem corresponder às do **documento de parâmetros**.
![Interface](../images/docs-section-ui.png)
Agora você pode usar a sintaxe do **Scriban** para criar seções em seu documento.
Por exemplo:
````
{{ if UI == "NG" }}
* O argumento `-u` especifica o framework de IU, `angular` neste caso.
{{ end }}
{{ if DB == "Mongo" }}
* O argumento `-d` especifica o provedor de banco de dados, `mongodb` neste caso.
{{ end }}
{{ if Tiered == "Yes" }}
* O argumento `--tiered` é usado para criar uma solução em camadas em que o servidor de autenticação, as camadas de IU e API são fisicamente separadas.
{{ end }}
````
Você também pode usar variáveis em um texto, adicionando o sufixo **_Value** à sua chave:
```txt
Este documento pressupõe que você prefere usar **{{ UI_Value }}** como o framework de IU e **{{ DB_Value }}** como o provedor de banco de dados.
```
Além disso, as chaves **Document_Language_Code** e **Document_Version** são predefinidas se você quiser obter o código do idioma ou a versão do documento atual (isso pode ser útil para criar links que redirecionam para outro sistema de documentação em outro domínio).
------
**AVISO IMPORTANTE**: O Scriban usa "{{" e "}}" para a sintaxe. Portanto, você deve usar blocos de escape se for usá-los em seu documento (um documento Angular, por exemplo). Consulte a [documentação do Scriban](https://github.com/lunet-io/scriban/blob/master/doc/language.md#13-escape-block) para obter mais informações.
### 8- Criando o Documento de Navegação
O documento de navegação é o menu principal da página de documentos. Ele está localizado no lado esquerdo da página. É um arquivo `JSON`. Dê uma olhada no exemplo de documento de navegação abaixo para entender a estrutura.
```json
{
"items":[
{
"text":"Item de Menu de Exemplo - 1",
"items":[
{
"text":"Item de Menu de Exemplo - 1.1",
"items":[
{
"text":"Item de Menu de Exemplo - 1.1.1",
"path":"SampleMenuItem_1_1_1.md"
}
]
},
{
"text":"Item de Menu de Exemplo - 1.2",
"items":[
{
"text":"Item de Menu de Exemplo - 1.2.1",
"path":"SampleMenuItem_1_2_1.md"
},
{
"text":"Item de Menu de Exemplo - 1.2.2",
"path":"SampleMenuItem_1_2_2.md"
}
]
}
]
},
{
"text":"Item de Menu de Exemplo - 2",
"items":[
{
"text":"Item de Menu de Exemplo - 2.1",
"items":[
{
"text":"Item de Menu de Exemplo - 2.1.1",
"path":"SampleMenuItem_2_1_1.md"
}
]
}
]
}
]
}
```
O exemplo acima de arquivo `JSON` renderiza o menu de navegação abaixo como `HTML`.
![Menu de navegação](../images/docs-module_download-sample-navigation-menu.png)
Finalmente, um novo Módulo de Documentação é adicionado ao seu projeto, que é alimentado pelo GitHub.
## Pesquisa de Texto Completo (Elastic Search)
O módulo de documentação suporta pesquisa de texto completo usando o Elastic Search. Ele não está habilitado por padrão. Você pode configurar `DocsElasticSearchOptions` para habilitá-lo.
```csharp
Configure<DocsElasticSearchOptions>(options =>
{
options.Enable = true;
options.IndexName = "your_index_name"; //o nome do índice padrão é abp_documents
});
```
O `Índice` é criado automaticamente após o início da aplicação se o `Índice` não existir.
`DefaultElasticClientProvider` é responsável por criar `IElasticClient`. Por padrão, ele lê a `Url` do Elastic Search da `IConfiguration`.
Se o seu `IElasticClient` precisar de configurações adicionais, use a substituição do serviço `IElasticClientProvider` e substitua-o no sistema de [injeção de dependência](../Dependency-Injection.md).
```json
{
"ElasticSearch": {
"Url": "http://localhost:9200"
}
}
```
## Destacando Linhas
Você pode aplicar destaque a linhas de código específicas ou a um intervalo de linhas sequenciais.
Veja os exemplos a seguir:
```
```C# {3, 5}
public class Book : Entity<Guid>
{
public string Name { get; set; }
public string Surname { get; set; }
}
```
```
```
```C# {2-4}
public class Book : Entity<Guid>
{
public string Name { get; set; }
public string Surname { get; set; }
}
```
```
```
```C# {1, 2-4}
public class Book : Entity<Guid>
{
public string Name { get; set; }
public string Surname { get; set; }
}
```
```
---
## Próximo
O Módulo de Documentação também está disponível como um aplicativo independente. Confira [VoloDocs](../Apps/VoloDocs).

105
docs/pt-BR/Modules/Feature-Management.md

@ -0,0 +1,105 @@
# Módulo de Gerenciamento de Recursos
O módulo de Gerenciamento de Recursos implementa a interface `IFeatureManagementStore` definida pelo [Sistema de Recursos](../Features.md).
> Este documento aborda apenas o módulo de gerenciamento de recursos que persiste os valores dos recursos em um banco de dados. Consulte o documento [recursos](../Features.md) para obter mais informações sobre o sistema de recursos.
## Como Instalar
Este módulo vem pré-instalado (como pacotes NuGet/NPM). Você pode continuar a usá-lo como pacote e obter atualizações facilmente, ou pode incluir seu código-fonte em sua solução (consulte o comando `get-source` [CLI](../CLI.md)) para desenvolver seu próprio módulo personalizado.
### O Código Fonte
O código-fonte deste módulo pode ser acessado [aqui](https://github.com/abpframework/abp/tree/dev/modules/feature-management). O código-fonte é licenciado com [MIT](https://choosealicense.com/licenses/mit/), portanto, você pode usá-lo e personalizá-lo livremente.
## Interface do Usuário
### Diálogo de Gerenciamento de Recursos
O módulo de gerenciamento de recursos fornece um diálogo reutilizável para gerenciar recursos relacionados a um objeto. Por exemplo, o [Módulo de Gerenciamento de Inquilinos](Tenant-Management.md) o utiliza para gerenciar os recursos dos inquilinos na página de Gerenciamento de Inquilinos.
![features-module-opening](../images/features-module-opening.png)
Quando você clica em *Ações* -> *Recursos* para um inquilino, o diálogo de gerenciamento de recursos é aberto. Uma captura de tela de exemplo deste diálogo com dois recursos definidos:
![features-modal](../images/features-modal.png)
Neste diálogo, você pode habilitar, desabilitar ou definir valores para os recursos de um inquilino.
## IFeatureManager
`IFeatureManager` é o serviço principal fornecido por este módulo. Ele é usado para ler e alterar os valores de configuração para os inquilinos em um aplicativo multi-inquilino. `IFeatureManager` é normalmente usado pelo *Diálogo de Gerenciamento de Recursos*. No entanto, você pode injetá-lo se precisar definir um valor de recurso.
> Se você apenas deseja ler os valores dos recursos, use o `IFeatureChecker` conforme explicado no documento [Recursos](../Features.md).
**Exemplo: Obter/definir o valor de um recurso para um inquilino**
````csharp
using System;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.FeatureManagement;
namespace Demo
{
public class MyService : ITransientDependency
{
private readonly IFeatureManager _featureManager;
public MyService(IFeatureManager featureManager)
{
_featureManager = featureManager;
}
public async Task SetFeatureDemoAsync(Guid tenantId, string value)
{
await _featureManager
.SetForTenantAsync(tenantId, "Recurso1", value);
var currentValue = await _featureManager
.GetOrNullForTenantAsync("Recurso1", tenantId);
}
}
}
````
## Provedores de Gerenciamento de Recursos
O Módulo de Gerenciamento de Recursos é extensível, assim como o [sistema de recursos](../Features.md). Você pode estendê-lo definindo provedores de gerenciamento de recursos. Existem 3 provedores de gerenciamento de recursos pré-construídos registrados na seguinte ordem:
* `DefaultValueFeatureManagementProvider`: Obtém o valor do valor padrão da definição do recurso. Ele não pode definir o valor padrão, pois os valores padrão são codificados na definição do recurso.
* `EditionFeatureManagementProvider`: Obtém ou define os valores dos recursos para uma edição. A edição é um grupo de recursos atribuídos a inquilinos. O sistema de edição não foi implementado pelo módulo de Gerenciamento de Inquilinos. Você pode implementá-lo por conta própria ou adquirir o [Módulo SaaS](https://commercial.abp.io/modules/Volo.Saas) do ABP Commercial, que o implementa e também fornece mais recursos SaaS, como assinatura e pagamento.
* `TenantFeatureManagementProvider`: Obtém ou define os valores dos recursos para inquilinos.
`IFeatureManager` usa esses provedores nos métodos de obtenção/definição. Normalmente, cada provedor de gerenciamento de recursos define métodos de extensão no serviço `IFeatureManager` (como `SetForTenantAsync` definido pelo provedor de gerenciamento de recursos de inquilinos).
Se você deseja criar seu próprio provedor, implemente a interface `IFeatureManagementProvider` ou herde da classe base `FeatureManagementProvider`:
````csharp
public class CustomFeatureProvider : FeatureManagementProvider
{
public override string Name => "Custom";
public CustomFeatureProvider(IFeatureManagementStore store)
: base(store)
{
}
}
````
A classe base `FeatureManagementProvider` faz a implementação padrão (usando o `IFeatureManagementStore`) para você. Você pode substituir os métodos base conforme necessário. Todo provedor deve ter um nome exclusivo, que é `Custom` neste exemplo (mantenha-o curto, pois ele é salvo no banco de dados para cada registro de valor de recurso).
Depois de criar sua classe de provedor, você deve registrá-la usando a classe de opções `FeatureManagementOptions` [options class](../Options.md):
````csharp
Configure<FeatureManagementOptions>(options =>
{
options.Providers.Add<CustomFeatureProvider>();
});
````
A ordem dos provedores é importante. Os provedores são executados na ordem inversa. Isso significa que o `CustomFeatureProvider` é executado primeiro neste exemplo. Você pode inserir seu provedor em qualquer ordem na lista `Providers`.
## Veja também
* [Recursos](../Features.md)

321
docs/pt-BR/Modules/Identity.md

@ -0,0 +1,321 @@
# Módulo de Gerenciamento de Identidade
O módulo de identidade é usado para gerenciar funções, usuários e suas permissões, com base na biblioteca de identidade da Microsoft.
## Como instalar
Este módulo já vem pré-instalado (como pacotes NuGet/NPM). Você pode continuar a usá-lo como pacote e obter atualizações facilmente, ou pode incluir seu código-fonte em sua solução (consulte o comando `get-source` [CLI](../CLI.md)) para desenvolver seu próprio módulo personalizado.
### O Código-fonte
O código-fonte deste módulo pode ser acessado [aqui](https://github.com/abpframework/abp/tree/dev/modules/identity). O código-fonte é licenciado com [MIT](https://choosealicense.com/licenses/mit/), então você pode usá-lo e personalizá-lo livremente.
## Interface do Usuário
Este módulo fornece opções de interface do usuário [Blazor](../UI/Blazor/Overall.md), [Angular](../UI/Angular/Quick-Start.md) e [MVC / Razor Pages](../UI/AspNetCore/Overall.md).
### Itens do Menu
Este módulo adiciona um item de menu *Gerenciamento de Identidade* no menu *Administração*:
![identity-module-menu](../images/identity-module-menu.png)
Os itens do menu e as páginas relacionadas são autorizados. Isso significa que o usuário atual deve ter as permissões relacionadas para torná-los visíveis. A função `admin` (e os usuários com essa função - como o usuário `admin`) já possui essas permissões. Se você deseja habilitar permissões para outras funções/usuários, abra a caixa de diálogo *Permissões* na página *Funções* ou *Usuários* e marque as permissões conforme mostrado abaixo:
![identity-module-permissions](../images/identity-module-permissions.png)
Consulte o documento de [Autorização](../Authorization.md) para entender o sistema de permissões.
### Páginas
Esta seção apresenta as principais páginas fornecidas por este módulo.
#### Usuários
Esta página é usada para ver a lista de usuários. Você pode criar/editar e excluir usuários, atribuir usuários a funções.
![identity-module-users](../images/identity-module-users.png)
Um usuário pode ter zero ou mais funções. Os usuários herdam permissões de suas funções. Além disso, você pode atribuir permissões diretamente aos usuários (clicando no botão *Ações*, em seguida, selecionando *Permissões*).
#### Funções
As funções são usadas para agrupar permissões e atribuí-las aos usuários.
![identity-module-roles](../images/identity-module-roles.png)
Além do nome da função, existem duas propriedades de uma função:
* `Padrão`: Se uma função for marcada como "padrão", essa função será atribuída aos novos usuários por padrão quando eles se registrarem na aplicação (usando o [Módulo de Conta](Account.md)).
* `Público`: Uma função pública de um usuário pode ser vista por outros usuários na aplicação. Essa funcionalidade não tem uso no módulo de identidade, mas é fornecida como uma funcionalidade que você pode querer usar em sua própria aplicação.
## Outras Funcionalidades
Esta seção abrange algumas outras funcionalidades fornecidas por este módulo que não possuem páginas de interface do usuário.
### Unidades Organizacionais
As unidades organizacionais (OU) podem ser usadas para agrupar usuários e entidades de forma hierárquica.
#### Entidade Unidade Organizacional
Uma OU é representada pela entidade **UnidadeOrganizacional**. As propriedades fundamentais desta entidade são:
- **TenantId**: Id do locatário desta OU. Pode ser nulo para OUs do host.
- **ParentId**: Id da OU pai. Pode ser nulo se esta for uma OU raiz.
- **Código**: Um código de string hierárquico que é único para um locatário.
- **DisplayName**: Nome exibido da OU.
#### Árvore de Organização
Como uma OU pode ter um pai, todas as OUs de um locatário estão em uma estrutura de **árvore**. Existem algumas regras para esta árvore:
- Pode haver mais de uma raiz (onde o `ParentId` é `null`).
- Há um limite para a contagem de filhos de primeiro nível de uma OU (por causa do comprimento fixo da unidade de código OU explicado abaixo).
#### Código da OU
O código da OU é gerado automaticamente e mantido pelo serviço `GerenciadorUnidadeOrganizacional`. É uma string que se parece com isso:
"**00001.00042.00005**"
Este código pode ser usado para consultar facilmente o banco de dados para todos os filhos de uma OU (recursivamente). Existem algumas regras para este código (aplicadas automaticamente quando você usa o `GerenciadorUnidadeOrganizacional`):
- É **único** para um [locatário](../Multi-Tenancy.md).
- Todos os filhos da mesma OU têm códigos que **começam com o código da OU pai**.
- É de **comprimento fixo** e baseado no nível da OU na árvore, conforme mostrado no exemplo.
- Embora o código da OU seja único, ele pode ser **alterado** se você mover a OU relacionada.
Observe que você deve referenciar uma OU pelo Id, não pelo Código, porque o Código pode ser alterado posteriormente.
#### Gerenciador de Unidade Organizacional
A classe `GerenciadorUnidadeOrganizacional` pode ser [injetada](../Dependency-Injection.md) e usada para gerenciar OUs. Casos de uso comuns são:
- Criar, atualizar ou excluir uma OU
- Mover uma OU na árvore de OUs.
- Obter informações sobre a árvore de OUs e seus itens.
### Log de Segurança de Identidade
O sistema de log de segurança registra algumas operações ou alterações importantes em sua conta (como *login* e *alteração de senha*). Você também pode salvar o log de segurança, se necessário.
Você pode injetar e usar `GerenciadorLogSegurancaIdentidade` ou `IGerenciadorLogSeguranca` para gravar logs de segurança. Ele criará um objeto de log por padrão e preencherá alguns valores comuns, como `CreationTime`, `ClientIpAddress`, `BrowserInfo`, `usuário/locatário atual`, etc. Claro, você pode substituí-los.
```cs
await GerenciadorLogSegurancaIdentidade.SalvarAsync(new ContextoLogSegurancaIdentidade()
{
Identidade = "IdentityServer",
Ação = "AlterarSenha"
});
```
Configure `OpcoesLogSegurancaAbp` para fornecer o nome do aplicativo (no caso de você ter várias aplicações e desejar distinguir as aplicações nos logs) para o log ou desativar esse recurso.
```cs
Configure<OpcoesLogSegurancaAbp>(opcoes =>
{
opcoes.NomeAplicativo = "AbpSecurityTest";
});
```
## Opções
`OpcoesIdentidade` é a classe de [opções](../Options.md) padrão fornecida pela biblioteca de [identidade](https://docs.microsoft.com/en-us/aspnet/core/security/authentication/identity) da Microsoft. Portanto, você pode definir essas opções no método `ConfigureServices` da sua classe de [módulo](../Module-Development-Basics.md).
**Exemplo: Definir o comprimento mínimo necessário das senhas**
````csharp
Configure<OpcoesIdentidade>(opcoes =>
{
opcoes.Senha.ComprimentoMinimo = 5;
});
````
O ABP leva essas opções um passo adiante e permite que você as altere em tempo de execução usando o [sistema de configurações](../Settings.md). Você pode [injetar](../Dependency-Injection.md) `IGerenciadorConfiguracao` e usar um dos métodos `Set...` para alterar os valores das opções para um usuário, um locatário ou globalmente para todos os usuários.
**Exemplo: Alterar o comprimento mínimo necessário das senhas para o locatário atual**
````csharp
public class MeuServico : IDependencyTransient
{
private readonly IGerenciadorConfiguracao _gerenciadorConfiguracao;
public MeuServico(IGerenciadorConfiguracao gerenciadorConfiguracao)
{
_gerenciadorConfiguracao = gerenciadorConfiguracao;
}
public async Task AlterarComprimentoMinSenha(int comprimentoMin)
{
await _gerenciadorConfiguracao.DefinirParaLocatarioAtualAsync(
NomesConfiguracaoIdentidade.Senha.ComprimentoMinimo,
comprimentoMin.ToString()
);
}
}
````
A classe `NomesConfiguracaoIdentidade` (no namespace `Volo.Abp.Identity.Settings`) define constantes para os nomes das configurações.
## Eventos Distribuídos
Este módulo define os seguintes ETOs (Event Transfer Objects) para permitir que você se inscreva em alterações nas entidades do módulo;
* `UserEto` é publicado em alterações feitas em uma entidade `IdentityUser`.
* `IdentityRoleEto` é publicado em alterações feitas em uma entidade `IdentityRole`.
* `IdentityClaimTypeEto` é publicado em alterações feitas em uma entidade `IdentityClaimType`.
* `OrganizationUnitEto` é publicado em alterações feitas em uma entidade `OrganizationUnit`.
**Exemplo: Ser notificado quando um novo usuário for criado**
````csharp
public class MeuManipulador :
IManipuladorEventoDistribuido<EntityCreatedEto<UserEto>>,
IDependencyTransient
{
public async Task ManipularEventoAsync(EntityCreatedEto<UserEto> evento)
{
UserEto user = evento.Entity;
// TODO: ...
}
}
````
`UserEto` e `IdentityRoleEto` são configurados para publicar automaticamente os eventos. Você deve configurar você mesmo para os outros. Consulte o documento de [Distributed Event Bus](../Distributed-Event-Bus.md) para aprender detalhes dos eventos pré-definidos.
> A inscrição nos eventos distribuídos é especialmente útil para cenários distribuídos (como arquitetura de microsserviços). Se você está construindo uma aplicação monolítica ou ouvindo eventos no mesmo processo que executa o Módulo de Identidade, então a inscrição nos [eventos locais](../Local-Event-Bus.md) pode ser mais eficiente e fácil.
## Internos
Esta seção abrange alguns detalhes internos do módulo que você não precisa muito, mas pode precisar usar em alguns casos.
### Camada de Domínio
#### Agregados
##### Usuário
Um usuário é geralmente uma pessoa que faz login e usa a aplicação.
* `IdentityUser` (raiz do agregado): Representa um usuário no sistema.
* `IdentityUserRole` (coleção): Funções do usuário.
* `IdentityUserClaim` (coleção): Reivindicações personalizadas do usuário.
* `IdentityUserLogin` (coleção): Logins externos do usuário.
* `IdentityUserToken` (coleção): Tokens do usuário (usados pelos serviços de identidade da Microsoft).
##### Função
Uma função é tipicamente um grupo de permissões para atribuir aos usuários.
* `IdentityRole` (raiz do agregado): Representa uma função no sistema.
* `IdentityRoleClaim` (coleção): Reivindicações personalizadas da função.
##### Tipo de Reivindicação
Um tipo de reivindicação é uma definição de uma reivindicação personalizada que pode ser atribuída a outras entidades (como funções e usuários) no sistema.
* `IdentityClaimType` (raiz do agregado): Representa uma definição de tipo de reivindicação. Ele contém algumas propriedades (por exemplo, Obrigatório, Regex, Descrição, ValueType) para definir o tipo de reivindicação e as regras de validação.
##### Log de Segurança de Identidade
Um objeto `IdentitySecurityLog` representa uma operação relacionada à autenticação (como *login*) no sistema.
* `IdentitySecurityLog` (raiz do agregado): Representa um log de segurança no sistema.
##### Unidade Organizacional
Uma unidade organizacional é uma entidade em uma estrutura hierárquica.
* ```OrganizationUnit``` (raiz do agregado): Representa uma unidade organizacional no sistema.
* ```Roles``` (coleção): Funções da unidade organizacional.
#### Repositórios
Os seguintes repositórios personalizados são definidos para este módulo:
* `IIdentityUserRepository`
* `IIdentityRoleRepository`
* `IIdentityClaimTypeRepository`
* ```IIdentitySecurityLogRepository```
* ```IOrganizationUnitRepository```
#### Serviços de Domínio
##### Gerenciador de Usuário
`IdentityUserManager` é usado para gerenciar usuários, suas funções, reivindicações, senhas, e-mails, etc. Ele é derivado da classe `UserManager<T>` da Microsoft Identity, onde `T` é `IdentityUser`.
##### Gerenciador de Função
`IdentityRoleManager` é usado para gerenciar funções e suas reivindicações. Ele é derivado da classe `RoleManager<T>` da Microsoft Identity, onde `T` é `IdentityRole`.
##### Gerenciador de Tipo de Reivindicação
`IdenityClaimTypeManager` é usado para realizar algumas operações para a raiz do agregado `IdentityClaimType`.
##### Gerenciador de Unidade Organizacional
```OrganizationUnitManager``` é usado para realizar algumas operações para a raiz do agregado ```OrganizationUnit```.
##### Gerenciador de Log de Segurança
```IdentitySecurityLogManager``` é usado para salvar logs de segurança.
### Camada de Aplicação
#### Serviços de Aplicação
* `IdentityUserAppService` (implementa `IIdentityUserAppService`): Implementa os casos de uso da interface do usuário de gerenciamento de usuários.
* `IdentityRoleAppService` (implementa `IIdentityRoleAppService`): Implementa os casos de uso da interface do usuário de gerenciamento de funções.
* `IdentityClaimTypeAppService` (implementa `IIdentityClaimTypeAppService`): Implementa os casos de uso da interface do usuário de gerenciamento de tipos de reivindicação.
* `IdentitySettingsAppService` (implementa `IIdentitySettingsAppService`): Usado para obter e atualizar configurações para o módulo de identidade.
* `IdentityUserLookupAppService` (implementa `IIdentityUserLookupAppService`): Usado para obter informações de um usuário por `id` ou `userName`. É destinado a ser usado internamente pelo framework ABP.
* `ProfileAppService` (implementa `IProfileAppService`): Usado para alterar o perfil de um usuário e a senha.
* ```IdentitySecurityLogAppService``` (implementa ```IIdentitySecurityLogAppService```): Implementa os casos de uso da interface do usuário de logs de segurança.
* ```OrganizationUnitAppService``` (implementa ```OrganizationUnitAppService```): Implementa os casos de uso da interface do usuário de gerenciamento de unidades organizacionais.
### Provedores de Banco de Dados
Este módulo fornece opções de [Entity Framework Core](../Entity-Framework-Core.md) e [MongoDB](../MongoDB.md) para o banco de dados.
#### Entity Framework Core
O pacote NuGet [Volo.Abp.Identity.EntityFrameworkCore](https://www.nuget.org/packages/Volo.Abp.Identity.EntityFrameworkCore) implementa a integração do EF Core.
##### Tabelas do Banco de Dados
* **AbpRoles**
* AbpRoleClaims
* **AbpUsers**
* AbpUserClaims
* AbpUserLogins
* AbpUserRoles
* AbpUserTokens
* **AbpClaimTypes**
* **AbpOrganizationUnits**
* AbpOrganizationUnitRoles
* AbpUserOrganizationUnits
* **AbpSecurityLogs**
#### MongoDB
O pacote NuGet [Volo.Abp.Identity.MongoDB](https://www.nuget.org/packages/Volo.Abp.Identity.MongoDB) implementa a integração do MongoDB.
##### Coleções do Banco de Dados
* **AbpRoles**
* **AbpUsers**
* **AbpClaimTypes**
* **AbpOrganizationUnits**
* **AbpSecurityLogs**
#### Propriedades Comuns do Banco de Dados
Você pode definir as seguintes propriedades da classe `AbpIdentityDbProperties` para alterar as opções do banco de dados:
* `DbTablePrefix` (`Abp` por padrão) é o prefixo para os nomes das tabelas/coleções.
* `DbSchema` (`null` por padrão) é o esquema do banco de dados.
* `ConnectionStringName` (`AbpIdentity` por padrão) é o nome da [string de conexão](../Connection-Strings.md) para este módulo.
Essas são propriedades estáticas. Se você quiser definir, faça isso no início de sua aplicação (normalmente, em `Program.cs`).

175
docs/pt-BR/Modules/IdentityServer.md

@ -0,0 +1,175 @@
# Módulo IdentityServer
O módulo IdentityServer fornece uma integração completa com o framework [IdentityServer4](https://github.com/IdentityServer/IdentityServer4) (IDS), que oferece recursos avançados de autenticação, como logon único e controle de acesso a API. Este módulo persiste clientes, recursos e outros objetos relacionados ao IDS no banco de dados. **Este módulo foi substituído pelo** [módulo OpenIddict](https://docs.abp.io/en/abp/latest/Modules/OpenIddict) após o ABP v6.0 nos modelos de inicialização.
> Observação: Você não pode usar os módulos IdentityServer e OpenIddict juntos. Eles são bibliotecas separadas de provedor OpenID para a mesma função.
## Como instalar
Você não precisa deste módulo quando estiver usando o módulo OpenIddict. No entanto, se você deseja continuar usando o IdentityServer4 para suas aplicações, você pode instalar este módulo e remover o módulo OpenIddict. Você pode continuar a usá-lo como pacote e obter atualizações facilmente, ou pode incluir seu código-fonte em sua solução (consulte o comando `get-source` [CLI](../CLI.md)) para desenvolver seu módulo personalizado.
### O código-fonte
O código-fonte deste módulo pode ser acessado [aqui](https://github.com/abpframework/abp/tree/dev/modules/identityserver). O código-fonte é licenciado com [MIT](https://choosealicense.com/licenses/mit/), então você pode usá-lo e personalizá-lo livremente.
## Interface do usuário
Este módulo implementa a lógica de domínio e as integrações com o banco de dados, mas não fornece nenhuma interface do usuário. A interface de gerenciamento é útil se você precisar adicionar clientes e recursos dinamicamente. Nesse caso, você pode construir a interface de gerenciamento por conta própria ou considerar a compra do [ABP Commercial](https://commercial.abp.io/), que fornece a interface de gerenciamento para este módulo.
## Relações com outros módulos
Este módulo é baseado no [módulo Identity](Identity.md) e possui um [pacote de integração](https://www.nuget.org/packages/Volo.Abp.Account.Web.IdentityServer) com o [módulo Account](Account.md).
## Opções
### AbpIdentityServerBuilderOptions
`AbpIdentityServerBuilderOptions` pode ser configurado no método `PreConfigureServices` do seu [módulo](https://docs.abp.io/en/abp/latest/Module-Development-Basics) do Identity Server. Exemplo:
````csharp
public override void PreConfigureServices(ServiceConfigurationContext context)
{
PreConfigure<AbpIdentityServerBuilderOptions>(builder =>
{
// Defina as opções aqui...
});
}
````
Propriedades de `AbpIdentityServerBuilderOptions`:
* `UpdateJwtSecurityTokenHandlerDefaultInboundClaimTypeMap` (padrão: true): Atualiza `JwtSecurityTokenHandler.DefaultInboundClaimTypeMap` para ser compatível com as reivindicações do Identity Server.
* `UpdateAbpClaimTypes` (padrão: true): Atualiza `AbpClaimTypes` para ser compatível com as reivindicações do Identity Server.
* `IntegrateToAspNetIdentity` (padrão: true): Integra ao ASP.NET Identity.
* `AddDeveloperSigningCredential` (padrão: true): Defina como false para suprimir a chamada AddDeveloperSigningCredential() no IIdentityServerBuilder.
`IIdentityServerBuilder` pode ser configurado no método `PreConfigureServices` do seu [módulo](https://docs.abp.io/en/abp/latest/Module-Development-Basics) do Identity Server. Exemplo:
````csharp
public override void PreConfigureServices(ServiceConfigurationContext context)
{
PreConfigure<IIdentityServerBuilder>(builder =>
{
builder.AddSigningCredential(...);
});
}
````
## Internos
### Camada de Domínio
#### Agregados
##### ApiResource
Os recursos da API são necessários para permitir que os clientes solicitem tokens de acesso.
* `ApiResource` (raiz do agregado): Representa um recurso da API no sistema.
* `ApiSecret` (coleção): segredos do recurso da API.
* `ApiScope` (coleção): escopos do recurso da API.
* `ApiResourceClaim` (coleção): reivindicações do recurso da API.
##### Client
Os clientes representam aplicativos que podem solicitar tokens do seu Identity Server.
* `Client` (raiz do agregado): Representa um aplicativo cliente do Identity Server.
* `ClientScope` (coleção): Escopos do cliente.
* `ClientSecret` (coleção): Segredos do cliente.
* `ClientGrantType` (coleção): Tipos de concessão do cliente.
* `ClientCorsOrigin` (coleção): Origens CORS do cliente.
* `ClientRedirectUri` (coleção): URIs de redirecionamento do cliente.
* `ClientPostLogoutRedirectUri` (coleção): URIs de redirecionamento de logout do cliente.
* `ClientIdPRestriction` (coleção): Restrições de provedor do cliente.
* `ClientClaim` (coleção): Reivindicações do cliente.
* `ClientProperty` (coleção): Propriedades personalizadas do cliente.
##### PersistedGrant
Persisted Grants armazena AuthorizationCodes, RefreshTokens e UserConsent.
* `PersistedGrant` (raiz do agregado): Representa um PersistedGrant para o servidor de identidade.
##### IdentityResource
Os recursos de identidade são dados como ID do usuário, nome ou endereço de e-mail de um usuário.
* `IdentityResource` (raiz do agregado): Representa um recurso de identidade do Identity Server.
* `IdentityClaim` (coleção): Reivindicações do recurso de identidade.
#### Repositórios
Os seguintes repositórios personalizados são definidos para este módulo:
* `IApiResourceRepository`
* `IClientRepository`
* `IPersistentGrantRepository`
* `IIdentityResourceRepository`
#### Serviços de Domínio
Este módulo não contém nenhum serviço de domínio, mas substitui os serviços abaixo;
* `AbpProfileService` (Usado quando `AbpIdentityServerBuilderOptions.IntegrateToAspNetIdentity` é true)
* `AbpClaimsService`
* `AbpCorsPolicyService`
### Configurações
Este módulo não define nenhuma configuração.
### Camada de Aplicação
#### Serviços de Aplicação
* `ApiResourceAppService` (implementa `IApiResourceAppService`): Implementa os casos de uso da interface de gerenciamento de recursos da API.
* `IdentityServerClaimTypeAppService` (implementa `IIdentityServerClaimTypeAppService`): Usado para obter a lista de reivindicações.
* `ApiResourceAppService` (implementa `IApiResourceAppService`): Implementa os casos de uso da interface de gerenciamento de recursos da API.
* `IdentityResourceAppService` (implementa `IIdentityResourceAppService`): Implementa os casos de uso da interface de gerenciamento de recursos de identidade.
### Provedores de Banco de Dados
#### Comum
##### Prefixo de Tabela/Collection e Esquema
Todas as tabelas/collections usam o prefixo `IdentityServer` por padrão. Defina as propriedades estáticas na classe `AbpIdentityServerDbProperties` se você precisar alterar o prefixo da tabela ou definir um nome de esquema (se suportado pelo seu provedor de banco de dados).
##### String de Conexão
Este módulo usa `AbpIdentityServer` como nome da string de conexão. Se você não definir uma string de conexão com esse nome, ela será usada a string de conexão `Default`.
Consulte a documentação sobre [strings de conexão](https://docs.abp.io/en/abp/latest/Connection-Strings) para obter mais detalhes.
#### Entity Framework Core
##### Tabelas
* **IdentityServerApiResources**
* IdentityServerApiSecrets
* IdentityServerApiScopes
* IdentityServerApiScopeClaims
* IdentityServerApiClaims
* **IdentityServerClients**
* IdentityServerClientScopes
* IdentityServerClientSecrets
* IdentityServerClientGrantTypes
* IdentityServerClientCorsOrigins
* IdentityServerClientRedirectUris
* IdentityServerClientPostLogoutRedirectUris
* IdentityServerClientIdPRestrictions
* IdentityServerClientClaims
* IdentityServerClientProperties
* **IdentityServerPersistedGrants**
* **IdentityServerIdentityResources**
* IdentityServerIdentityClaims
#### MongoDB
##### Coleções
* **IdentityServerApiResources**
* **IdentityServerClients**
* **IdentityServerPersistedGrants**
* **IdentityServerIdentityResources**

32
docs/pt-BR/Modules/Index.md

@ -0,0 +1,32 @@
# Módulos de Aplicação
ABP é um **framework de aplicação modular** que consiste em dezenas de **pacotes NuGet & NPM**. Ele também fornece uma infraestrutura completa para construir seus próprios módulos de aplicação, que podem ter entidades, serviços, integração de banco de dados, APIs, componentes de interface do usuário, entre outros.
Existem **dois tipos de módulos**. Eles não têm nenhuma diferença estrutural, mas são categorizados por funcionalidade e propósito:
* [**Módulos do framework**](https://github.com/abpframework/abp/tree/dev/framework/src): Estes são **módulos principais do framework** como cache, envio de e-mails, temas, segurança, serialização, validação, integração com o EF Core, integração com o MongoDB... etc. Eles não possuem funcionalidades de aplicação/negócio, mas facilitam o desenvolvimento diário fornecendo infraestrutura comum, integração e abstrações.
* [**Módulos de aplicação**](https://github.com/abpframework/abp/tree/dev/modules): Esses módulos implementam funcionalidades específicas de aplicação/negócio, como blogs, gerenciamento de documentos, gerenciamento de identidade, gerenciamento de locatários... etc. Eles geralmente possuem suas próprias entidades, serviços, APIs e componentes de interface do usuário.
## Módulos de Aplicação de Código Aberto
Existem alguns módulos de aplicação **gratuitos e de código aberto** desenvolvidos e mantidos como parte do ABP Framework.
* [**Conta**](Account.md): Fornece uma interface de usuário para o gerenciamento de contas e permite que o usuário faça login/registo na aplicação.
* [**Registro de Auditoria**](Audit-Logging.md): Persiste registros de auditoria em um banco de dados.
* [**Trabalhos em Segundo Plano**](Background-Jobs.md): Persiste trabalhos em segundo plano ao usar o gerenciador de trabalhos em segundo plano padrão.
* [**Kit CMS**](Cms-Kit/Index.md): Um conjunto de recursos reutilizáveis de *Sistema de Gerenciamento de Conteúdo*.
* [**Documentação**](Docs.md): Usado para criar um site de documentação técnica. A própria documentação do ABP já utiliza este módulo.
* [**Gerenciamento de Recursos**](Feature-Management.md): Usado para persistir e gerenciar os [recursos](../Features.md).
* **[Identidade](Identity.md)**: Gerencia unidades organizacionais, funções, usuários e suas permissões, com base na biblioteca Microsoft Identity.
* [**IdentityServer**](IdentityServer.md): Integra-se ao IdentityServer4.
* [**OpenIddict**](OpenIddict.md): Integra-se ao OpenIddict.
* [**Gerenciamento de Permissões**](Permission-Management.md): Usado para persistir permissões.
* **[Gerenciamento de Configurações](Setting-Management.md)**: Usado para persistir e gerenciar as [configurações](../Settings.md).
* [**Gerenciamento de Locatários**](Tenant-Management.md): Gerencia locatários para uma aplicação [multi-locatário](../Multi-Tenancy.md).
* [**Explorador de Arquivos Virtuais**](Virtual-File-Explorer.md): Fornece uma interface de usuário simples para visualizar arquivos em um [sistema de arquivos virtual](../Virtual-File-System.md).
Veja [o repositório do GitHub](https://github.com/abpframework/abp/tree/dev/modules) para o código-fonte de todos os módulos.
## Módulos de Aplicação Comerciais
A licença [ABP Commercial](https://commercial.abp.io/) fornece **módulos de aplicação pré-construídos adicionais** em cima do framework ABP. Veja a [lista de módulos](https://commercial.abp.io/modules) fornecida pelo ABP Commercial.

514
docs/pt-BR/Modules/OpenIddict.md

@ -0,0 +1,514 @@
## Módulo ABP OpenIddict
O módulo OpenIddict fornece uma integração com o [OpenIddict](https://github.com/openiddict/openiddict-core), que oferece recursos avançados de autenticação, como logon único, logoff único e controle de acesso à API. Este módulo persiste aplicativos, escopos e outros objetos relacionados ao OpenIddict no banco de dados.
## Como instalar
Este módulo já vem pré-instalado (como pacotes NuGet/NPM). Você pode continuar a usá-lo como um pacote e obter atualizações facilmente, ou pode incluir seu código-fonte em sua solução (consulte o comando `get-source` [CLI](../CLI.md)) para desenvolver seu próprio módulo personalizado.
### O código-fonte
O código-fonte deste módulo pode ser acessado [aqui](https://github.com/abpframework/abp/tree/dev/modules/openiddict). O código-fonte é licenciado pela [MIT](https://choosealicense.com/licenses/mit/), portanto, você pode usá-lo e personalizá-lo livremente.
## Interface do usuário
Este módulo implementa a lógica de domínio e as integrações com o banco de dados, mas não fornece nenhuma interface do usuário. A interface de gerenciamento é útil se você precisar adicionar aplicativos e escopos dinamicamente. Nesse caso, você pode construir a interface de gerenciamento por conta própria ou considerar a compra do [ABP Commercial](https://commercial.abp.io/), que fornece a interface de gerenciamento para este módulo.
## Relações com outros módulos
Este módulo é baseado no [Módulo de Identidade](Identity.md) e possui um [pacote de integração](https://www.nuget.org/packages/Volo.Abp.Account.Web.OpenIddict) com o [Módulo de Conta](Account.md).
## Opções
### OpenIddictBuilder
O `OpenIddictBuilder` pode ser configurado no método `PreConfigureServices` do seu [módulo](https://docs.abp.io/en/abp/latest/Module-Development-Basics) OpenIddict.
Exemplo:
```csharp
public override void PreConfigureServices(ServiceConfigurationContext context)
{
PreConfigure<OpenIddictBuilder>(builder =>
{
// Defina as opções aqui...
});
}
```
O `OpenIddictBuilder` contém vários métodos de extensão para configurar os serviços do OpenIddict:
- `AddServer()` registra os serviços do servidor de token OpenIddict no contêiner de DI. Contém as configurações do `OpenIddictServerBuilder`.
- `AddCore()` registra os serviços principais do OpenIddict no contêiner de DI. Contém as configurações do `OpenIddictCoreBuilder`.
- `AddValidation()` registra os serviços de validação de token OpenIddict no contêiner de DI. Contém as configurações do `OpenIddictValidationBuilder`.
### OpenIddictCoreBuilder
O `OpenIddictCoreBuilder` contém métodos de extensão para configurar os serviços principais do OpenIddict.
Exemplo:
```csharp
public override void PreConfigureServices(ServiceConfigurationContext context)
{
PreConfigure<OpenIddictCoreBuilder>(builder =>
{
// Defina as opções aqui...
});
}
```
Esses serviços contêm:
- Adição de `ApplicationStore`, `AuthorizationStore`, `ScopeStore`, `TokenStore`.
- Substituição de `ApplicationManager`, `AuthorizationManager`, `ScopeManager`, `TokenManager`.
- Substituição de `ApplicationStoreResolver`, `AuthorizationStoreResolver`, `ScopeStoreResolver`, `TokenStoreResolver`.
- Definição de `DefaultApplicationEntity`, `DefaultAuthorizationEntity`, `DefaultScopeEntity`, `DefaultTokenEntity`.
### OpenIddictServerBuilder
O `OpenIddictServerBuilder` contém métodos de extensão para configurar os serviços do servidor OpenIddict.
Exemplo:
```csharp
public override void PreConfigureServices(ServiceConfigurationContext context)
{
PreConfigure<OpenIddictServerBuilder>(builder =>
{
// Defina as opções aqui...
});
}
```
Esses serviços contêm:
- Registro de claims, escopos.
- Definição do URI `Issuer` que é usado como endereço base para os URIs de endpoint retornados pelo endpoint de descoberta.
- Adição de chaves de assinatura de desenvolvimento, chaves de criptografia/assinatura, credenciais e certificados.
- Adição/remoção de manipuladores de eventos.
- Habilitação/desabilitação de tipos de concessão.
- Definição de URIs de endpoint do servidor de autenticação.
### OpenIddictValidationBuilder
O `OpenIddictValidationBuilder` contém métodos de extensão para configurar os serviços de validação do OpenIddict.
Exemplo:
```csharp
public override void PreConfigureServices(ServiceConfigurationContext context)
{
PreConfigure<OpenIddictValidationBuilder>(builder =>
{
// Defina as opções aqui...
});
}
```
Esses serviços contêm:
- `AddAudiences()` para servidores de recursos.
- `SetIssuer()` define o URI usado para determinar a localização real do documento de configuração do OAuth 2.0/OpenID Connect ao usar a descoberta do provedor.
- `SetConfiguration()` para configurar `OpenIdConnectConfiguration`.
- `UseIntrospection()` para usar a introspecção em vez da validação local/direta.
- Adição de chave de criptografia, credenciais e certificados.
- Adição/remoção de manipuladores de eventos.
- `SetClientId()` para definir o identificador do cliente `client_id` ao se comunicar com o servidor de autorização remoto (por exemplo, para introspecção).
- `SetClientSecret()` para definir o identificador `client_secret` ao se comunicar com o servidor de autorização remoto (por exemplo, para introspecção).
- `EnableAuthorizationEntryValidation()` para habilitar a validação de autorização para garantir que o `access token` ainda seja válido fazendo uma chamada ao banco de dados para cada solicitação da API. *Observação:* Isso pode ter um impacto negativo no desempenho e só pode ser usado com um servidor de autorização baseado no OpenIddict.
- `EnableTokenEntryValidation()` para habilitar a validação de autorização para garantir que o `access token` ainda seja válido fazendo uma chamada ao banco de dados para cada solicitação da API. *Observação:* Isso pode ter um impacto negativo no desempenho e é necessário quando o servidor OpenIddict está configurado para usar tokens de referência.
- `UseLocalServer()` para registrar os serviços de integração de validação/servidor OpenIddict.
- `UseAspNetCore()` para registrar os serviços de validação do OpenIddict para o ASP.NET Core no contêiner de DI.
## Internos
### Camada de Domínio
#### Agregados
##### OpenIddictApplication
OpenIddictApplications representam os aplicativos que podem solicitar tokens do seu servidor OpenIddict.
- `OpenIddictApplications` (raiz do agregado): Representa um aplicativo OpenIddict.
- `ClientId` (string): O identificador do cliente associado ao aplicativo atual.
- `ClientSecret` (string): O segredo do cliente associado ao aplicativo atual. Pode ser criptografado ou hash para fins de segurança.
- `ConsentType` (string): O tipo de consentimento associado ao aplicativo atual.
- `DisplayName` (string): O nome de exibição associado ao aplicativo atual.
- `DisplayNames` (string): Os nomes de exibição localizados associados ao aplicativo atual serializados como um objeto JSON.
- `Permissions` (string): As permissões associadas ao aplicativo atual, serializadas como um array JSON.
- `PostLogoutRedirectUris` (string): As URLs de retorno de chamada de logoff associadas ao aplicativo atual, serializadas como um array JSON.
- `Properties` (string): As propriedades adicionais associadas ao aplicativo atual serializadas como um objeto JSON ou nulo.
- `RedirectUris` (string): As URLs de retorno de chamada associadas ao aplicativo atual, serializadas como um array JSON.
- `Requirements` (string): Os requisitos associados ao aplicativo atual.
- `Type` (string): O tipo de aplicativo associado ao aplicativo atual.
- `ClientUri` (string): URI para obter mais informações sobre o cliente.
- `LogoUri` (string): URI para o logotipo do cliente.
##### OpenIddictAuthorization
OpenIddictAuthorizations são usadas para manter os escopos permitidos e os tipos de fluxo de autorização.
- `OpenIddictAuthorization` (raiz do agregado): Representa uma autorização OpenIddict.
- `ApplicationId` (Guid?): O aplicativo associado à autorização atual.
- `Properties` (string): As propriedades adicionais associadas à autorização atual serializadas como um objeto JSON ou nulo.
- `Scopes` (string): Os escopos associados à autorização atual, serializados como um array JSON.
- `Status` (string): O status da autorização atual.
- `Subject` (string): O assunto associado à autorização atual.
- `Type` (string): O tipo da autorização atual.
##### OpenIddictScope
OpenIddictScopes são usados para manter os escopos dos recursos.
- `OpenIddictScope` (raiz do agregado): Representa um escopo OpenIddict.
- `Description` (string): A descrição pública associada ao escopo atual.
- `Descriptions` (string): As descrições públicas localizadas associadas ao escopo atual, serializadas como um objeto JSON.
- `DisplayName` (string): O nome de exibição associado ao escopo atual.
- `DisplayNames` (string): Os nomes de exibição localizados associados ao escopo atual serializados como um objeto JSON.
- `Name` (string): O nome único associado ao escopo atual.
- `Properties` (string): As propriedades adicionais associadas ao escopo atual serializadas como um objeto JSON ou nulo.
- `Resources` (string): Os recursos associados ao escopo atual, serializados como um array JSON.
##### OpenIddictToken
OpenIddictTokens são usados para persistir os tokens do aplicativo.
- `OpenIddictToken` (raiz do agregado): Representa um token OpenIddict.
- `ApplicationId` (Guid?): O aplicativo associado ao token atual.
- `AuthorizationId` (Guid?): A autorização associada ao token atual.
- `CreationDate` (DateTime?): A data de criação UTC do token atual.
- `ExpirationDate` (DateTime?): A data de expiração UTC do token atual.
- `Payload` (string): O payload do token atual, se aplicável. Usado apenas para tokens de referência e pode ser criptografado por motivos de segurança.
- `Properties` (string): As propriedades adicionais associadas ao token atual serializadas como um objeto JSON ou nulo.
- `RedemptionDate` (DateTime?): A data de resgate UTC do token atual.
- `Status` (string): O status da autorização atual.
- `ReferenceId` (string): O identificador de referência associado ao token atual, se aplicável. Usado apenas para tokens de referência e pode ser criptografado ou hash por motivos de segurança.
- `Status` (string): O status do token atual.
- `Subject` (string): O assunto associado ao token atual.
- `Type` (string): O tipo do token atual.
#### Armazenamentos
Este módulo implementa os armazenamentos do OpenIddict:
- `IAbpOpenIdApplicationStore`
- `IOpenIddictAuthorizationStore`
- `IOpenIddictScopeStore`
- `IOpenIddictTokenStore`
#### AbpOpenIddictStoreOptions
Você pode configurar o `PruneIsolationLevel/DeleteIsolationLevel` do `AbpOpenIddictStoreOptions` para definir o nível de isolamento para as operações de armazenamento, pois diferentes bancos de dados têm diferentes níveis de isolamento.
##### Repositórios
Os seguintes repositórios personalizados são definidos neste módulo:
- `IOpenIddictApplicationRepository`
- `IOpenIddictAuthorizationRepository`
- `IOpenIddictScopeRepository`
- `IOpenIddictTokenRepository`
##### Serviços de Domínio
Este módulo não contém nenhum serviço de domínio, mas substitui o serviço abaixo:
- `AbpApplicationManager` usado para popular/obter informações do `AbpApplicationDescriptor` que contém `ClientUri` e `LogoUri`.
### Provedores de Banco de Dados
#### Comum
##### Prefixo de Tabela/Collection e Esquema
Todas as tabelas/collections usam o prefixo `OpenIddict` por padrão. Defina as propriedades estáticas na classe `AbpOpenIddictDbProperties` se você precisar alterar o prefixo da tabela ou definir um nome de esquema (se suportado pelo seu provedor de banco de dados).
##### String de Conexão
Este módulo usa `AbpOpenIddict` como nome da string de conexão. Se você não definir uma string de conexão com esse nome, ela será usada a string de conexão `Default`.
Consulte a documentação sobre [strings de conexão](https://docs.abp.io/en/abp/latest/Connection-Strings) para obter detalhes.
#### Entity Framework Core
##### Tabelas
- **OpenIddictApplications**
- **OpenIddictAuthorizations**
- **OpenIddictScopes**
- **OpenIddictTokens**
#### MongoDB
##### Coleções
- **OpenIddictApplications**
- **OpenIddictAuthorizations**
- **OpenIddictScopes**
- **OpenIddictTokens**
## Módulo ASP.NET Core
Este módulo integra o ASP.NET Core, com controladores MVC embutidos para quatro protocolos. Ele usa o modo de passagem do OpenIddict [Pass-through mode](https://documentation.openiddict.com/guides/index.html#pass-through-mode).
```cs
AuthorizeController -> connect/authorize
TokenController -> connect/token
LogoutController -> connect/logout
UserInfoController -> connect/userinfo
```
> A implementação do **fluxo de dispositivo** será feita no módulo comercial.
#### AbpOpenIddictAspNetCoreOptions
`AbpOpenIddictAspNetCoreOptions` pode ser configurado no método `PreConfigureServices` do seu [módulo](https://docs.abp.io/en/abp/latest/Module-Development-Basics) OpenIddict.
Exemplo:
```csharp
PreConfigure<AbpOpenIddictAspNetCoreOptions>(options =>
{
// Defina as opções aqui...
});
```
Propriedades do `AbpOpenIddictAspNetCoreOptions`:
- `UpdateAbpClaimTypes(default: true)`: Atualiza `AbpClaimTypes` para ser compatível com as reivindicações do Openiddict.
- `AddDevelopmentEncryptionAndSigningCertificate(default: true)`: Registra (e gera, se necessário) um certificado de criptografia/assinatura de desenvolvimento específico do usuário. Este é um certificado usado para assinar e criptografar os tokens e apenas para **ambiente de desenvolvimento**. Você deve defini-lo como **false** para ambientes não de desenvolvimento.
> `AddDevelopmentEncryptionAndSigningCertificate` não pode ser usado em aplicativos implantados no IIS ou no Azure App Service: tentar usá-los no IIS ou no Azure App Service resultará em uma exceção lançada em tempo de execução (a menos que o pool de aplicativos esteja configurado para carregar um perfil de usuário). Para evitar isso, considere criar certificados autoassinados e armazená-los no repositório de certificados X.509 da(s) máquina(s) host. Consulte: https://documentation.openiddict.com/configuration/encryption-and-signing-credentials.html#registering-a-development-certificate
#### Removendo automaticamente Tokens/Autorizações Órfãs
A tarefa em segundo plano que remove automaticamente tokens/autorizações órfãs pode ser configurada por `TokenCleanupOptions`.
`TokenCleanupOptions` pode ser configurado no método `ConfigureServices` do seu [módulo](https://docs.abp.io/en/abp/latest/Module-Development-Basics) OpenIddict.
Exemplo:
```csharp
Configure<TokenCleanupOptions>(options =>
{
// Defina as opções aqui...
});
```
Propriedades do `TokenCleanupOptions`:
- `IsCleanupEnabled` (padrão: true): Habilita/desabilita a limpeza de token.
- `CleanupPeriod` (padrão: 3.600.000 ms): Define o período de limpeza.
- `DisableAuthorizationPruning`: Define um booleano indicando se a poda de autorizações deve ser desabilitada.
- `DisableTokenPruning`: Define um booleano indicando se a poda de tokens deve ser desabilitada.
- `MinimumAuthorizationLifespan` (padrão: 14 dias): Define a vida útil mínima que as autorizações devem ter para serem podadas. Não pode ser inferior a 10 minutos.
- `MinimumTokenLifespan` (padrão: 14 dias): Define a vida útil mínima que os tokens devem ter para serem podados. Não pode ser inferior a 10 minutos.
#### Atualizando Reivindicações em Access_token e Id_token
[Claims Principal Factory](https://docs.abp.io/en/abp/latest/Authorization#claims-principal-factory) pode ser usado para adicionar/remover reivindicações ao `ClaimsPrincipal`.
O serviço `AbpDefaultOpenIddictClaimsPrincipalHandler` adicionará tipos de reivindicações `Name`, `Email` e `Role` ao `access_token` e `id_token`, outras reivindicações são adicionadas apenas ao `access_token` por padrão e remove a reivindicação secreta `SecurityStampClaimType` do `Identity`.
Crie um serviço que herde de `IAbpOpenIddictClaimsPrincipalHandler` e adicione-o ao DI para controlar totalmente os destinos das reivindicações.
```cs
public class MyClaimDestinationsHandler : IAbpOpenIddictClaimsPrincipalHandler, ITransientDependency
{
public virtual Task HandleAsync(AbpOpenIddictClaimsPrincipalHandlerContext context)
{
foreach (var claim in context.Principal.Claims)
{
if (claim.Type == MyClaims.MyClaimsType)
{
claim.SetDestinations(OpenIddictConstants.Destinations.AccessToken, OpenIddictConstants.Destinations.IdentityToken);
}
if (claim.Type == MyClaims.MyClaimsType2)
{
claim.SetDestinations(OpenIddictConstants.Destinations.AccessToken);
}
}
return Task.CompletedTask;
}
}
Configure<AbpOpenIddictClaimsPrincipalOptions>(options =>
{
options.ClaimsPrincipalHandlers.Add<MyClaimDestinationsHandler>();
});
```
Para obter informações detalhadas, consulte: [OpenIddict claim destinations](https://documentation.openiddict.com/configuration/claim-destinations.html)
#### Desabilitar a Criptografia do AccessToken
O ABP desabilita a `criptografia do access token` por padrão para compatibilidade, mas pode ser habilitada manualmente, se necessário.
```cs
public override void PreConfigureServices(ServiceConfigurationContext context)
{
PreConfigure<OpenIddictServerBuilder>(builder =>
{
builder.Configure(options => options.DisableAccessTokenEncryption = false);
});
}
```
https://documentation.openiddict.com/configuration/token-formats.html#disabling-jwt-access-token-encryption
### Processo de Solicitação/Resposta
O `OpenIddict.Server.AspNetCore` adiciona um esquema de autenticação (`Name: OpenIddict.Server.AspNetCore, handler: OpenIddictServerAspNetCoreHandler`) e implementa a interface `IAuthenticationRequestHandler`.
Ele será executado primeiro no `AuthenticationMiddleware` e pode interromper o processamento da solicitação atual. Caso contrário, o `DefaultAuthenticateScheme` será chamado e continuará a executar o pipeline.
O `OpenIddictServerAspNetCoreHandler` chamará vários manipuladores embutidos (manipulando solicitações e respostas) e o manipulador processará de acordo com o contexto ou ignorará a lógica que não tem relação com ele.
Exemplo de uma solicitação de token:
```
POST /connect/token HTTP/1.1
Content-Type: application/x-www-form-urlencoded
grant_type=password&
client_id=AbpApp&
client_secret=1q2w3e*&
username=admin&
password=1q2w3E*&
scope=AbpAPI offline_access
```
Esta solicitação será processada por vários manipuladores. Eles confirmarão o tipo de endpoint da solicitação, verificarão `HTTP/HTTPS`, verificarão se os parâmetros da solicitação (`client, scope`, etc.) são válidos e existem no banco de dados, etc. Várias verificações de protocolo. E construir um objeto `OpenIddictRequest`, Se houver erros, o conteúdo da resposta pode ser definido e interromper diretamente a solicitação atual.
Se tudo estiver ok, a solicitação irá para nosso controlador de processamento (por exemplo, `TokenController`), podemos obter um `OpenIddictRequest` da solicitação HTTP neste momento. O restante será baseado neste objeto.
Verifique o `username` e `password` na solicitação. Se estiver correto, crie um objeto `ClaimsPrincipal` e retorne um `SignInResult`, que usa o nome do esquema de autenticação `OpenIddict.Validation.AspNetCore`, chamará o `OpenIddictServerAspNetCoreHandler` para processamento.
O `OpenIddictServerAspNetCoreHandler` fará algumas verificações para gerar json e substituir o conteúdo da resposta HTTP.
O `ForbidResult` `ChallengeResult` são todos os tipos de processamento acima.
Se você precisar personalizar o OpenIddict, será necessário substituir/excluir/adicionar novos manipuladores e fazer com que ele seja executado na ordem correta.
Consulte: https://documentation.openiddict.com/guides/index.html#events-model
### PKCE
https://documentation.openiddict.com/configuration/proof-key-for-code-exchange.html
### Definindo o Tempo de Vida dos Tokens
Atualize o método `PreConfigureServices` do arquivo AuthServerModule (ou HttpApiHostModule se você não tiver um servidor de autenticação separado) :
```csharp
PreConfigure<OpenIddictServerBuilder>(builder =>
{
builder.SetAuthorizationCodeLifetime(TimeSpan.FromMinutes(30));
builder.SetAccessTokenLifetime(TimeSpan.FromMinutes(30));
builder.SetIdentityTokenLifetime(TimeSpan.FromMinutes(30));
builder.SetRefreshTokenLifetime(TimeSpan.FromDays(14));
});
```
### Token de Atualização
Para usar o token de atualização, ele deve ser suportado pelo OpenIddictServer e o `refresh_token` deve ser solicitado pelo aplicativo.
> **Observação:** O aplicativo Angular já está configurado para usar o `refresh_token`.
#### Configurando o OpenIddictServer
Atualize o **OpenIddictDataSeedContributor**, adicione `OpenIddictConstants.GrantTypes.RefreshToken` aos tipos de concessão no método `CreateApplicationAsync`:
```csharp
await CreateApplicationAsync(
...
grantTypes: new List<string> //Fluxo híbrido
{
OpenIddictConstants.GrantTypes.AuthorizationCode,
OpenIddictConstants.GrantTypes.Implicit,
OpenIddictConstants.GrantTypes.RefreshToken,
},
...
```
> **Observação:** Você precisa recriar esse cliente se já tiver gerado o banco de dados.
#### Configurando o Aplicativo:
Você precisa solicitar o escopo **offline_access** para poder receber o `refresh_token`.
Nos aplicativos **Razor/MVC, Blazor-Server**, adicione `options.Scope.Add("offline_access");` às opções **OpenIdConnect**. Esses modelos de aplicativo usam autenticação por cookie por padrão e têm as opções de expiração do cookie definidas como:
```csharp
.AddCookie("Cookies", options =>
{
options.ExpireTimeSpan = TimeSpan.FromDays(365);
})
```
[Cookie ExpireTimeSpan ignorará a expiração do access_token](https://learn.microsoft.com/en-us/dotnet/api/Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationOptions.ExpireTimeSpan?view=aspnetcore-7.0&viewFallbackFrom=net-7.0) e o access_token expirado ainda será válido se for definido com um valor maior que o `refresh_token lifetime`. É recomendável manter o **Cookie ExpireTimeSpan** e o **Refresh Token lifetime** iguais, para que o novo token seja persistido no cookie.
Nos aplicativos **Blazor wasm**, adicione `options.ProviderOptions.DefaultScopes.Add("offline_access");` às opções **AddOidcAuthentication**.
Nos aplicativos **Angular**, adicione `offline_access` aos escopos **oAuthConfig** no arquivo *environment.ts*. (Os aplicativos Angular já têm essa configuração).
## Sobre a localização
Não localizamos nenhuma mensagem de erro no módulo OpenIddict, porque a especificação OAuth 2.0 restringe o conjunto de caracteres que você pode usar para os parâmetros de erro e error_description:
> A.7. "error" Syntax
> O elemento "error" é definido nas Seções 4.1.2.1, 4.2.2.1, 5.2, 7.2 e 8.5:
```
error = 1*NQSCHAR
```
> A.8. "error_description" Syntax
> O elemento "error_description" é definido nas Seções 4.1.2.1, 4.2.2.1, 5.2 e 7.2:
```
error-description = 1*NQSCHAR
NQSCHAR = %x20-21 / %x23-5B / %x5D-7E
```
## Projetos de demonstração
No diretório `app` do módulo, existem seis projetos (incluindo `angular`)
* `OpenIddict.Demo.Server`: Um aplicativo abp com módulos integrados (possui dois `clientes` e um `escopo`).
* `OpenIddict.Demo.API`: Aplicativo ASP NET Core API usando autenticação JwtBearer.
* `OpenIddict.Demo.Client.Mvc`: Aplicativo ASP NET Core MVC usando `OpenIdConnect` para autenticação.
* `OpenIddict.Demo.Client.Console`: Use `IdentityModel` para testar os vários endpoints do OpenIddict e chamar a API do `OpenIddict.Demo.API`.
* `OpenIddict.Demo.Client.BlazorWASM:` Aplicativo Blazor ASP NET Core usando `OidcAuthentication` para autenticação.
* `angular`: Um aplicativo angular que integra os módulos abp ng e usa oauth para autenticação.
#### Como executar?
Confirme a string de conexão do `appsettings.json` no projeto `OpenIddict.Demo.Server`. A execução do projeto criará automaticamente o banco de dados e inicializará os dados.
Após executar o projeto `OpenIddict.Demo.API`, você pode executar o restante dos projetos para testar.
## Guia de Migração
[Guia de Migração Passo a Passo do IdentityServer para o OpenIddict](../Migration-Guides/OpenIddict-Step-by-Step.md)

109
docs/pt-BR/Modules/Permission-Management.md

@ -0,0 +1,109 @@
# Módulo de Gerenciamento de Permissões
Este módulo implementa o `IPermissionStore` para armazenar e gerenciar valores de permissões em um banco de dados.
> Este documento aborda apenas o módulo de gerenciamento de permissões que persiste os valores de permissão em um banco de dados. Consulte o documento de [Autorização](../Authorization.md) para entender os sistemas de autorização e permissão.
## Como Instalar
Este módulo já vem pré-instalado (como pacotes NuGet/NPM). Você pode continuar a usá-lo como pacote e obter atualizações facilmente, ou pode incluir seu código-fonte em sua solução (consulte o comando `get-source` da [CLI](../CLI.md)) para desenvolver seu próprio módulo personalizado.
### O Código-fonte
O código-fonte deste módulo pode ser acessado [aqui](https://github.com/abpframework/abp/tree/dev/modules/permission-management). O código-fonte é licenciado com a licença [MIT](https://choosealicense.com/licenses/mit/), portanto, você pode usá-lo e personalizá-lo livremente.
## Interface do Usuário
### Diálogo de Gerenciamento de Permissões
O módulo de gerenciamento de permissões fornece um diálogo reutilizável para gerenciar permissões relacionadas a um objeto. Por exemplo, o [Módulo de Identidade](Identity.md) o utiliza para gerenciar as permissões de usuários e funções. A imagem a seguir mostra a página de Gerenciamento de Funções do Módulo de Identidade:
![permissions-module-open-dialog](../images/permissions-module-open-dialog.png)
Quando você clica em *Ações* -> *Permissões* para uma função, o diálogo de gerenciamento de permissões é aberto. Uma captura de tela de exemplo deste diálogo:
![permissions-module-dialog](../images/permissions-module-dialog.png)
Neste diálogo, você pode conceder permissões para a função selecionada. As abas no lado esquerdo representam os principais grupos de permissões e o lado direito contém as permissões definidas no grupo selecionado.
## IPermissionManager
`IPermissionManager` é o serviço principal fornecido por este módulo. Ele é usado para ler e alterar os valores de permissão. `IPermissionManager` é normalmente usado pelo *Diálogo de Gerenciamento de Permissões*. No entanto, você pode injetá-lo se precisar definir um valor de permissão.
> Se você apenas deseja ler/verificar os valores de permissão para o usuário atual, use o `IAuthorizationService` ou o atributo `[Authorize]`, conforme explicado no documento de [Autorização](../Authorization.md).
**Exemplo: Conceder permissões para funções e usuários usando o serviço `IPermissionManager`**
````csharp
public class MeuServico : ITransientDependency
{
private readonly IPermissionManager _permissionManager;
public MeuServico(IPermissionManager permissionManager)
{
_permissionManager = permissionManager;
}
public async Task ConcederPermissaoParaFuncaoDemoAsync(
string nomeFuncao, string permissao)
{
await _permissionManager
.SetForRoleAsync(nomeFuncao, permissao, true);
}
public async Task ConcederPermissaoParaUsuarioDemoAsync(
Guid idUsuario, string nomeFuncao, string permissao)
{
await _permissionManager
.SetForUserAsync(idUsuario, permissao, true);
}
}
````
## Provedores de Gerenciamento de Permissões
O Módulo de Gerenciamento de Permissões é extensível, assim como o [sistema de permissões](../Authorization.md). Você pode estendê-lo definindo provedores de gerenciamento de permissões.
O [Módulo de Identidade](Identity.md) define os seguintes provedores de gerenciamento de permissões:
* `UserPermissionManagementProvider`: Gerencia permissões baseadas em usuários.
* `RolePermissionManagementProvider`: Gerencia permissões baseadas em funções.
`IPermissionManager` usa esses provedores quando você obtém/define permissões. Você pode definir seu próprio provedor implementando o `IPermissionManagementProvider` ou herdando da classe base `PermissionManagementProvider`.
**Exemplo:**
````csharp
public class CustomPermissionManagementProvider : PermissionManagementProvider
{
public override string Name => "Custom";
public CustomPermissionManagementProvider(
IPermissionGrantRepository permissionGrantRepository,
IGuidGenerator guidGenerator,
ICurrentTenant currentTenant)
: base(
permissionGrantRepository,
guidGenerator,
currentTenant)
{
}
}
````
A classe base `PermissionManagementProvider` faz a implementação padrão (usando o `IPermissionGrantRepository`) para você. Você pode substituir os métodos base conforme necessário. Cada provedor deve ter um nome exclusivo, que é `Custom` neste exemplo (mantenha-o curto, pois ele é salvo no banco de dados para cada registro de valor de permissão).
Depois de criar sua classe de provedor, você deve registrá-la usando a classe de opções `PermissionManagementOptions` [options class](../Options.md):
````csharp
Configure<PermissionManagementOptions>(options =>
{
options.ManagementProviders.Add<CustomPermissionManagementProvider>();
});
````
A ordem dos provedores é importante. Os provedores são executados na ordem inversa. Isso significa que o `CustomPermissionManagementProvider` é executado primeiro neste exemplo. Você pode inserir seu provedor em qualquer ordem na lista `Providers`.
## Veja também
* [Autorização](../Authorization.md)

313
docs/pt-BR/Modules/Setting-Management.md

@ -0,0 +1,313 @@
# Módulo de Gerenciamento de Configurações
O Módulo de Gerenciamento de Configurações implementa a interface `ISettingStore` (consulte [o sistema de configurações](../Settings.md)) para armazenar os valores das configurações em um banco de dados e fornece a interface `ISettingManager` para gerenciar (alterar) os valores das configurações no banco de dados.
> O módulo de Gerenciamento de Configurações já está instalado e configurado nos [modelos de inicialização](../Startup-Templates/Index.md). Portanto, na maioria das vezes, você não precisa adicionar manualmente este módulo à sua aplicação.
## ISettingManager
`ISettingManager` é usado para obter e definir os valores das configurações. Exemplos:
````csharp
using System;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.SettingManagement;
namespace Demo
{
public class MyService : ITransientDependency
{
private readonly ISettingManager _settingManager;
// Injeta o serviço ISettingManager
public MyService(ISettingManager settingManager)
{
_settingManager = settingManager;
}
public async Task FooAsync()
{
Guid user1Id = ...;
Guid tenant1Id = ...;
// Obtém/define um valor de configuração para o usuário atual ou para o usuário especificado
string layoutType1 =
await _settingManager.GetOrNullForCurrentUserAsync("App.UI.LayoutType");
string layoutType2 =
await _settingManager.GetOrNullForUserAsync("App.UI.LayoutType", user1Id);
await _settingManager.SetForCurrentUserAsync("App.UI.LayoutType", "LeftMenu");
await _settingManager.SetForUserAsync(user1Id, "App.UI.LayoutType", "LeftMenu");
// Obtém/define um valor de configuração para o locatário atual ou para o locatário especificado
string layoutType3 =
await _settingManager.GetOrNullForCurrentTenantAsync("App.UI.LayoutType");
string layoutType4 =
await _settingManager.GetOrNullForTenantAsync("App.UI.LayoutType", tenant1Id);
await _settingManager.SetForCurrentTenantAsync("App.UI.LayoutType", "LeftMenu");
await _settingManager.SetForTenantAsync(tenant1Id, "App.UI.LayoutType", "LeftMenu");
// Obtém/define um valor de configuração global e padrão
string layoutType5 =
await _settingManager.GetOrNullGlobalAsync("App.UI.LayoutType");
string layoutType6 =
await _settingManager.GetOrNullDefaultAsync("App.UI.LayoutType");
await _settingManager.SetGlobalAsync("App.UI.LayoutType", "TopMenu");
}
}
}
````
Portanto, você pode obter ou definir um valor de configuração para diferentes provedores de valores de configuração (Padrão, Global, Usuário, Locatário... etc).
> Use a interface `ISettingProvider` em vez da `ISettingManager` se você apenas precisa ler os valores das configurações, pois ela implementa o cache e suporta todos os cenários de implantação. Você pode usar a `ISettingManager` se estiver criando uma interface de gerenciamento de configurações.
### Cache de Configurações
Os valores das configurações são armazenados em cache usando o sistema de [cache distribuído](../Caching.md). Sempre use o `ISettingManager` para alterar os valores das configurações, pois ele gerencia o cache para você.
## Provedores de Gerenciamento de Configurações
O módulo de Gerenciamento de Configurações é extensível, assim como o [sistema de configurações](../Settings.md). Você pode estendê-lo definindo provedores de gerenciamento de configurações. Existem 5 provedores de gerenciamento de configurações pré-construídos registrados na seguinte ordem:
* `DefaultValueSettingManagementProvider`: Obtém o valor do valor padrão da definição da configuração. Ele não pode definir o valor padrão, pois os valores padrão são codificados na definição da configuração.
* `ConfigurationSettingManagementProvider`: Obtém o valor do serviço [IConfiguration](../Configuration.md). Ele não pode definir o valor de configuração, pois não é possível alterar os valores de configuração em tempo de execução.
* `GlobalSettingManagementProvider`: Obtém ou define o valor global (em todo o sistema) para uma configuração.
* `TenantSettingManagementProvider`: Obtém ou define o valor da configuração para um locatário.
* `UserSettingManagementProvider`: Obtém o valor da configuração para um usuário.
O `ISettingManager` usa os provedores de gerenciamento de configurações nos métodos de obtenção/definição. Normalmente, cada provedor de gerenciamento de configurações define métodos de extensão no serviço `ISettingManagement` (como `SetForUserAsync` definido pelo provedor de gerenciamento de configurações de usuário).
Se você deseja criar seu próprio provedor, implemente a interface `ISettingManagementProvider` ou herde da classe base `SettingManagementProvider`:
````csharp
public class CustomSettingProvider : SettingManagementProvider, ITransientDependency
{
public override string Name => "Custom";
public CustomSettingProvider(ISettingManagementStore store)
: base(store)
{
}
}
````
A classe base `SettingManagementProvider` faz a implementação padrão (usando o `ISettingManagementStore`) para você. Você pode substituir os métodos base conforme necessário. Todo provedor deve ter um nome exclusivo, que é `Custom` neste exemplo (mantenha-o curto, pois ele é salvo no banco de dados para cada registro de valor de configuração).
Depois de criar sua classe de provedor, você deve registrá-la usando a classe de opções `SettingManagementOptions` [options class](../Options.md):
````csharp
Configure<SettingManagementOptions>(options =>
{
options.Providers.Add<CustomSettingProvider>();
});
````
A ordem dos provedores é importante. Os provedores são executados na ordem inversa. Isso significa que o `CustomSettingProvider` é executado primeiro neste exemplo. Você pode inserir seu provedor em qualquer ordem na lista `Providers`.
## Veja também
* [Configurações](../Settings.md)
## Interface de Gerenciamento de Configurações
O módulo de Gerenciamento de Configurações fornece a interface de configuração de e-mail por padrão.
![Interface de Configuração de E-mail](../images/setting-management-email-ui.png)
> Você pode clicar no botão Enviar e-mail de teste para enviar um e-mail de teste e verificar suas configurações de e-mail.
Ele é extensível; você pode adicionar suas guias a esta página para as configurações de sua aplicação.
### Interface de Usuário MVC
#### Criar um Componente de Visualização de Configuração
Crie a pasta `MySettingGroup` dentro da pasta `Components`. Adicione um novo componente de visualização. Nomeie-o como `MySettingGroupViewComponent`:
![MySettingGroupViewComponent](../images/my-setting-group-view-component.png)
Abra o arquivo `MySettingGroupViewComponent.cs` e altere todo o conteúdo conforme mostrado abaixo:
```csharp
public class MySettingGroupViewComponent : AbpViewComponent
{
public virtual IViewComponentResult Invoke()
{
return View("~/Components/MySettingGroup/Default.cshtml");
}
}
```
> Você também pode usar o método `InvokeAsync`, neste exemplo, usamos o método `Invoke`.
#### Default.cshtml
Crie um arquivo `Default.cshtml` dentro da pasta `MySettingGroup`.
Abra o arquivo `Default.cshtml` e altere todo o conteúdo conforme mostrado abaixo:
```html
<div>
<p>Página do meu grupo de configurações</p>
</div>
```
#### BookStoreSettingPageContributor
Crie um arquivo `BookStoreSettingPageContributor.cs` dentro da pasta `Settings`:
![BookStoreSettingPageContributor](../images/my-setting-group-page-contributor.png)
O conteúdo do arquivo é mostrado abaixo:
```csharp
public class BookStoreSettingPageContributor : ISettingPageContributor
{
public Task ConfigureAsync(SettingPageCreationContext context)
{
context.Groups.Add(
new SettingPageGroup(
"Volo.Abp.MySettingGroup",
"MySettingGroup",
typeof(MySettingGroupViewComponent),
order : 1
)
);
return Task.CompletedTask;
}
public Task<bool> CheckPermissionsAsync(SettingPageCreationContext context)
{
// Você pode verificar as permissões aqui
return Task.FromResult(true);
}
}
```
Abra o arquivo `BookStoreWebModule.cs` e adicione o seguinte código:
```csharp
Configure<SettingManagementPageOptions>(options =>
{
options.Contributors.Add(new BookStoreSettingPageContributor());
});
```
#### Executar a Aplicação
Acesse a rota `/SettingManagement` para ver as alterações:
![Guia de Configurações Personalizadas](../images/my-setting-group-ui.png)
### Interface de Usuário Blazor
#### Criar um Componente Razor
Crie a pasta `MySettingGroup` dentro da pasta `Pages`. Adicione um novo componente Razor. Nomeie-o como `MySettingGroupComponent`:
![MySettingGroupComponent](../images/my-setting-group-component.png)
Abra o arquivo `MySettingGroupComponent.razor` e altere todo o conteúdo conforme mostrado abaixo:
```csharp
<Row>
<p>meu grupo de configurações</p>
</Row>
```
#### BookStoreSettingComponentContributor
Crie um arquivo `BookStoreSettingComponentContributor.cs` dentro da pasta `Settings`:
![BookStoreSettingComponentContributor](../images/my-setting-group-component-contributor.png)
O conteúdo do arquivo é mostrado abaixo:
```csharp
public class BookStoreSettingComponentContributor : ISettingComponentContributor
{
public Task ConfigureAsync(SettingComponentCreationContext context)
{
context.Groups.Add(
new SettingComponentGroup(
"Volo.Abp.MySettingGroup",
"MySettingGroup",
typeof(MySettingGroupComponent),
order : 1
)
);
return Task.CompletedTask;
}
public Task<bool> CheckPermissionsAsync(SettingComponentCreationContext context)
{
// Você pode verificar as permissões aqui
return Task.FromResult(true);
}
}
```
Abra o arquivo `BookStoreBlazorModule.cs` e adicione o seguinte código:
```csharp
Configure<SettingManagementComponentOptions>(options =>
{
options.Contributors.Add(new BookStoreSettingComponentContributor());
});
```
#### Executar a Aplicação
Acesse a rota `/setting-management` para ver as alterações:
![Guia de Configurações Personalizadas](../images/my-setting-group-blazor.png)
### Interface de Usuário Angular
#### Criar um Componente
Crie um componente com o seguinte comando:
```bash
yarn ng generate component my-settings
```
Abra o arquivo `app.component.ts` e modifique o arquivo conforme mostrado abaixo:
```js
import { Component } from '@angular/core';
import { SettingTabsService } from '@abp/ng.setting-management/config'; // importando SettingTabsService
import { MySettingsComponent } from './my-settings/my-settings.component'; // importando MySettingsComponent
@Component(/* metadados do componente */)
export class AppComponent {
constructor(private settingTabs: SettingTabsService) // injetando MySettingsComponent
{
// adicionado abaixo
settingTabs.add([
{
name: 'MySettings',
order: 1,
requiredPolicy: 'chave da política aqui',
component: MySettingsComponent,
},
]);
}
}
```
#### Executar a Aplicação
Acesse a rota `/setting-management` para ver as alterações:
![Guia de Configurações Personalizadas](../images/custom-settings.png)

134
docs/pt-BR/Modules/Tenant-Management.md

@ -0,0 +1,134 @@
# Módulo de Gerenciamento de Inquilinos
O [Multi-Tenancy](../Multi-Tenancy.md) é uma das principais características do ABP Framework. Ele fornece a infraestrutura fundamental para construir sua própria solução SaaS (Software-as-a-Service). O sistema de multi-tenancy do ABP abstrai onde seus inquilinos são armazenados, fornecendo a interface `ITenantStore`. Tudo que você precisa fazer é implementar essa interface.
**O módulo de gerenciamento de inquilinos é uma implementação da interface `ITenantStore`. Ele armazena inquilinos em um banco de dados. Ele também fornece uma interface de usuário para gerenciar seus inquilinos e suas [funcionalidades](../Features.md).**
> Por favor, **consulte a documentação do [Multi-Tenancy](../Multi-Tenancy.md)** para entender o sistema de multi-tenancy do ABP Framework. Este documento se concentra no módulo de gerenciamento de inquilinos.
### Sobre o Módulo SaaS Comercial do ABP
O [Módulo SaaS](https://commercial.abp.io/modules/Volo.Saas) é uma implementação alternativa deste módulo com mais funcionalidades e possibilidades. Ele é distribuído como parte da assinatura do [ABP Commercial](https://commercial.abp.io/).
## Como Instalar
Este módulo vem pré-instalado (como pacotes NuGet/NPM) quando você [cria uma nova solução](https://abp.io/get-started) com o ABP Framework. Você pode continuar a usá-lo como pacote e obter atualizações facilmente, ou pode incluir seu código-fonte em sua solução (consulte o comando `get-source` da [CLI](../CLI.md)) para desenvolver seu próprio módulo personalizado.
### O Código Fonte
O código-fonte deste módulo pode ser acessado [aqui](https://github.com/abpframework/abp/tree/dev/modules/tenant-management). O código-fonte é licenciado com [MIT](https://choosealicense.com/licenses/mit/), então você pode usá-lo e personalizá-lo livremente.
## Interface de Usuário
Este módulo adiciona o item de menu "*Administração -> Gerenciamento de Inquilinos -> Inquilinos*" ao menu principal do aplicativo, que abre a página mostrada abaixo:
![module-tenant-management-page](../images/module-tenant-management-page.png)
Nesta página, você vê todos os inquilinos. Você pode criar um novo inquilino conforme mostrado abaixo:
![module-tenant-management-new-tenant](../images/module-tenant-management-new-tenant.png)
Neste modal;
* **Nome**: O nome único do inquilino. Se você usar subdomínios para seus inquilinos (como https://algum-inquilino.seu-domínio.com), este será o nome do subdomínio.
* **Endereço de E-mail do Administrador**: Endereço de e-mail do usuário administrador para este inquilino.
* **Senha do Administrador**: A senha do usuário administrador para este inquilino.
Quando você clica no botão *Ações* próximo a um inquilino, você verá as ações que pode realizar:
![module-tenant-management-actions](../images/module-tenant-management-actions.png)
### Gerenciando as Funcionalidades do Inquilino
A ação Funcionalidades abre um modal para habilitar/desabilitar/configurar [funcionalidades](../Features.md) para o inquilino relacionado. Aqui, um exemplo de modal:
![features-modal](../images/features-modal.png)
### Gerenciando as Funcionalidades do Host
O botão *Gerenciar Funcionalidades do Host* é usado para configurar as funcionalidades do lado do host, se você usar as funcionalidades do seu aplicativo também no lado do host.
## Eventos Distribuídos
Este módulo define os seguintes ETOs (Event Transfer Objects) para permitir que você se inscreva em alterações nas entidades do módulo;
- `TenantEto` é publicado em alterações feitas em uma entidade `Tenant`.
**Exemplo: Receber uma notificação quando um novo inquilino for criado**
```cs
public class MeuManipulador :
IDistributedEventHandler<EntityCreatedEto<TenantEto>>,
ITransientDependency
{
public async Task HandleEventAsync(EntityCreatedEto<TenantEto> eventData)
{
TenantEto tenant = eventData.Entity;
// TODO: ...
}
}
```
`TenantEto` é configurado para publicar automaticamente os eventos. Você deve configurar-se para os outros. Consulte o documento [Distributed Event Bus](https://github.com/abpframework/abp/blob/rel-7.3/docs/en/Distributed-Event-Bus.md) para aprender detalhes dos eventos pré-definidos.
> A inscrição nos eventos distribuídos é especialmente útil para cenários distribuídos (como arquitetura de microsserviços). Se você estiver construindo um aplicativo monolítico ou ouvindo eventos no mesmo processo que executa o Módulo de Gerenciamento de Inquilinos, então a inscrição nos [eventos locais](https://github.com/abpframework/abp/blob/rel-7.3/docs/en/Local-Event-Bus.md) pode ser mais eficiente e fácil.
## Internos
Esta seção pode ser usada como referência se você quiser [personalizar](../Customizing-Application-Modules-Guide.md) este módulo sem alterar [seu código-fonte](https://github.com/abpframework/abp/tree/dev/modules/tenant-management).
### Camada de Domínio
#### Agregados
* `Tenant`
#### Repositórios
* `ITenantRepository`
#### Serviços de Domínio
* `TenantManager`
### Camada de Aplicação
#### Serviços de Aplicação
* `TenantAppService`
#### Permissões
- `AbpTenantManagement.Tenants`: Gerenciamento de inquilinos.
- `AbpTenantManagement.Tenants.Create`: Criar um novo inquilino.
- `AbpTenantManagement.Tenants.Update`: Editar um inquilino existente.
- `AbpTenantManagement.Tenants.Delete`: Excluir um inquilino existente.
- `AbpTenantManagement.Tenants.ManageFeatures`: Gerenciar as funcionalidades dos inquilinos.
### Integração com o Entity Framework Core
* `TenantManagementDbContext` (implementa `ITenantManagementDbContext`)
**Tabelas do Banco de Dados:**
* `AbpTenants`
* `AbpTenantConnectionStrings`
### Integração com o MongoDB
* `TenantManagementMongoDbContext` (implementa `ITenantManagementMongoDbContext`)
**Coleções do Banco de Dados:**
* `AbpTenants` (inclui também a string de conexão)
## Avisos
O ABP Framework permite usar a abordagem *banco de dados por inquilino*, que permite que um inquilino tenha um banco de dados dedicado. Este módulo possui a infraestrutura fundamental para tornar essa implementação possível (consulte seu código-fonte), no entanto, ele não implementa a camada de aplicação e as funcionalidades de interface do usuário para fornecê-lo como uma implementação pronta para uso. Você pode implementar esses recursos por conta própria ou considerar o uso do [Módulo SaaS Comercial do ABP](https://docs.abp.io/en/commercial/latest/modules/saas), que o implementa completamente e fornece muito mais recursos de negócios.
## Veja Também
* [Multi-Tenancy](../Multi-Tenancy.md)
* [Módulo SaaS Comercial do ABP](https://docs.abp.io/en/commercial/latest/modules/saas)

87
docs/pt-BR/Modules/Virtual-File-Explorer.md

@ -0,0 +1,87 @@
# Módulo de Explorador de Arquivos Virtual
## O que é o Módulo de Explorador de Arquivos Virtual?
O Módulo de Explorador de Arquivos Virtual fornece uma interface de usuário simples para visualizar todos os arquivos no [sistema de arquivos virtual](../Virtual-File-System.md).
> O Módulo de Explorador de Arquivos Virtual não está instalado nos [modelos de inicialização](../Startup-Templates/Index.md). Portanto, você precisa adicionar manualmente este módulo à sua aplicação.
### Instalação
#### 1- Usando o ABP CLI
Recomenda-se usar o [ABP CLI](../CLI.md) para instalar o módulo. Abra a janela do CMD no diretório do arquivo de solução (`.sln`) e execute o seguinte comando:
```
abp add-module Volo.VirtualFileExplorer
```
> Se você ainda não o fez, primeiro precisa instalar o [ABP CLI](../CLI.md). Para outras opções de instalação, consulte [a página de descrição do pacote](https://abp.io/package-detail/Volo.Abp.VirtualFileExplorer.Web).
#### 2- Instalação manual
Ou você também pode instalar manualmente o pacote nuget no projeto `Acme.MyProject.Web`:
* Instale o pacote nuget [Volo.Abp.VirtualFileExplorer.Web](https://www.nuget.org/packages/Volo.Abp.VirtualFileExplorer.Web/) no projeto `Acme.MyProject.Web`.
`Install-Package Volo.Abp.VirtualFileExplorer.Web`
##### 2.1- Adicionando Dependências do Módulo
* Abra `MyProjectWebModule.cs` e adicione `typeof(AbpVirtualFileExplorerWebModule)` como mostrado abaixo;
```csharp
[DependsOn(
typeof(AbpVirtualFileExplorerWebModule),
typeof(MyProjectApplicationModule),
typeof(MyProjectEntityFrameworkCoreModule),
typeof(AbpAutofacModule),
typeof(AbpIdentityWebModule),
typeof(AbpAccountWebModule),
typeof(AbpAspNetCoreMvcUiBasicThemeModule)
)]
public class MyProjectWebModule : AbpModule
{
//...
}
```
##### 2.2- Adicionando Pacote NPM
* Abra `package.json` e adicione `@abp/virtual-file-explorer": "^2.9.0` como mostrado abaixo:
```json
{
"version": "1.0.0",
"name": "my-app",
"private": true,
"dependencies": {
"@abp/aspnetcore.mvc.ui.theme.basic": "^2.9.0",
"@abp/virtual-file-explorer": "^2.9.0"
}
}
```
Em seguida, abra o terminal de linha de comando na pasta do projeto `Acme.MyProject.Web` e execute o seguinte comando:
````bash
abp install-libs
````
Isso é tudo, agora execute a aplicação e navegue até `/VirtualFileExplorer`. Você verá a página do explorador de arquivos virtual:
![Virtual-File-Explorer](../images/virtual-file-explorer.png)
### Opções
Você pode desativar o módulo de explorador de arquivos virtual através das opções `AbpVirtualFileExplorerOptions`:
```csharp
public override void PreConfigureServices(ServiceConfigurationContext context)
{
PreConfigure<AbpVirtualFileExplorerOptions>(options =>
{
options.IsEnabled = false;
});
}
```

74
docs/pt-BR/UI/AspNetCore/AutoComplete-Select.md

@ -0,0 +1,74 @@
# ASP.NET Core MVC / Razor Pages: Auto-Complete Select
Um componente de seleção simples às vezes não é útil com uma grande quantidade de dados. O ABP fornece uma implementação de seleção que funciona com paginação e pesquisa no lado do servidor usando o [Select2](https://select2.org/). Ele funciona bem com escolhas únicas ou múltiplas.
Uma captura de tela pode ser mostrada abaixo.
| Único | Múltiplo |
| --- | --- |
| ![autocomplete-select-example](../../images/abp-select2-single.png) |![autocomplete-select-example](../../images/abp-select2-multiple.png) |
## Começando
Esta é uma funcionalidade central e é usada pelo ABP Framework. Não há instalação personalizada ou pacotes adicionais necessários.
## Uso
Um uso simples é apresentado abaixo.
```html
<select asp-for="Book.AuthorId"
class="auto-complete-select"
data-autocomplete-api-url="/api/app/author"
data-autocomplete-display-property="name"
data-autocomplete-value-property="id"
data-autocomplete-items-property="items"
data-autocomplete-filter-param-name="filter"
data-autocomplete-allow-clear="true">
<!-- Você pode definir a(s) opção(ões) selecionada(s) aqui -->
<option selected value="@SelectedAuthor.Id">@SelectedAuthor.Name</option>
</select>
```
O select deve ter a classe `auto-complete-select` e os seguintes atributos:
- `data-autocomplete-api-url`: * URL do endpoint da API para obter os itens da seleção. Será enviado uma requisição **GET** para esta URL.
- `data-autocomplete-display-property`: * Nome da propriedade para exibição. _(Por exemplo: `name` ou `title`. Nome da propriedade da entidade/dto.)_.
- `data-autocomplete-value-property`: * Nome da propriedade identificadora. _(Por exemplo: `id`)_.
- `data-autocomplete-items-property`: * Nome da propriedade da coleção no objeto de resposta. _(Por exemplo: `items`)_
- `data-autocomplete-filter-param-name`: * Nome da propriedade de texto de filtro. _(Por exemplo: `filter`)_.
- `data-autocomplete-selected-item-name`: Texto para exibir como item selecionado.
- `data-autocomplete-parent-selector`: Expressão seletora jQuery para o DOM pai. _(Se estiver em um modal, é sugerido enviar o seletor do modal como este parâmetro)_.
- `data-autocomplete-allow-clear`: Se `true`, permitirá limpar o valor selecionado. Valor padrão: `false`.
- `data-autocomplete-placeholder`: Texto de espaço reservado para exibir quando nenhum valor estiver selecionado.
Além disso, o(s) valor(es) selecionado(s) deve(m) ser definido(s) com as tags `<option>` dentro do select, uma vez que a paginação é aplicada e as opções selecionadas podem não ter sido carregadas ainda.
### Escolhas Múltiplas
O AutoComplete Select suporta escolhas múltiplas. Se a tag select tiver o atributo `multiple`, permitirá escolher várias opções.
```html
<select asp-for="Book.TagIds"
class="auto-complete-select"
multiple="multiple"
data-autocomplete-api-url="/api/app/tags"
data-autocomplete-display-property="name"
data-autocomplete-value-property="id"
data-autocomplete-items-property="items"
data-autocomplete-filter-param-name="filter">
@foreach(var tag in SelectedTags)
{
<option selected value="@tag.Id">@tag.Name</option>
}
</select>
```
Será automaticamente vinculado a uma coleção do tipo de valor definido.
```csharp
public List<Guid> TagIds { get; set; }
```
## Avisos
Se o usuário autenticado não tiver permissão na URL fornecida, o usuário receberá um erro de autorização. Tenha cuidado ao projetar esse tipo de interface de usuário.
Você pode criar um endpoint/método específico, [não autorizado](../../Authorization.md), para obter a lista de itens, para que a página possa recuperar dados de pesquisa de uma entidade dependente sem dar permissão de leitura completa aos usuários.

96
docs/pt-BR/UI/AspNetCore/Basic-Theme.md

@ -0,0 +1,96 @@
# ASP.NET Core MVC / Razor Pages: O Tema Básico
O Tema Básico é uma implementação de tema para a interface do usuário do ASP.NET Core MVC / Razor Pages. É um tema minimalista que não adiciona nenhum estilo além do [Bootstrap](https://getbootstrap.com/) básico. Você pode usar o Tema Básico como o **tema base** e construir seu próprio tema ou estilo em cima dele. Veja a seção *Customização*.
O Tema Básico possui suporte para idiomas da direita para a esquerda (RTL).
> Se você está procurando um tema profissional e pronto para uso empresarial, você pode conferir o [Tema Lepton](https://commercial.abp.io/themes), que faz parte do [ABP Commercial](https://commercial.abp.io/).
> Veja o documento [Theming](Theming.md) para aprender sobre temas.
## Instalação
Se você precisa instalar manualmente este tema, siga os passos abaixo:
* Instale o pacote NuGet [Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic](https://www.nuget.org/packages/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic) em seu projeto web.
* Adicione `AbpAspNetCoreMvcUiBasicThemeModule` no atributo `[DependsOn(...)]` para a sua [classe de módulo](../../Module-Development-Basics.md) no projeto web.
* Instale o pacote NPM [@abp/aspnetcore.mvc.ui.theme.basic](https://www.npmjs.com/package/@abp/aspnetcore.mvc.ui.theme.basic) em seu projeto web (por exemplo, `npm install @abp/aspnetcore.mvc.ui.theme.basic` ou `yarn add @abp/aspnetcore.mvc.ui.theme.basic`).
* Execute o comando `abp install-libs` em um terminal de linha de comando na pasta do projeto web.
## Layouts
O Tema Básico implementa os layouts padrão. Todos os layouts implementam as seguintes partes:
* [Bundles](Bundling-Minification.md) globais
* [Alertas de página](Page-Alerts.md)
* [Hooks de layout](Layout-Hooks.md)
* Recursos de [widget](Widgets.md)
### O Layout da Aplicação
![basic-theme-application-layout](../../images/basic-theme-application-layout.png)
O Layout da Aplicação implementa as seguintes partes, além das partes comuns mencionadas acima:
* Marca
* [Menu](Navigation-Menu.md) principal
* [Toolbar](Toolbars.md) principal com seleção de idioma e menu do usuário
### O Layout da Conta
![basic-theme-account-layout](../../images/basic-theme-account-layout.png)
O Layout da Conta implementa as seguintes partes, além das partes comuns mencionadas acima:
* Marca
* [Menu](Navigation-Menu.md) principal
* [Toolbar](Toolbars.md) principal com seleção de idioma e menu do usuário
* Área de troca de inquilino
### Layout Vazio
O layout vazio é vazio, como o nome sugere. No entanto, ele implementa as partes comuns mencionadas acima.
## Customização
Você tem duas opções para personalizar este tema:
### Sobrescrevendo Estilos/Componentes
Nesta abordagem, você continua a usar o tema como pacotes NuGet e NPM e personaliza as partes que precisa. Existem várias maneiras de personalizá-lo;
#### Sobrescrever os Estilos
1. Crie um arquivo CSS na pasta `wwwroot` do seu projeto:
![example-global-styles](../../images/example-global-styles.png)
2. Adicione o arquivo de estilo ao bundle global, no método `ConfigureServices` da sua [classe de módulo](../../Module-Development-Basics.md):
````csharp
Configure<AbpBundlingOptions>(options =>
{
options.StyleBundles.Configure(BasicThemeBundles.Styles.Global, bundle =>
{
bundle.AddFiles("/styles/global-styles.css");
});
});
````
#### Sobrescrever os Componentes
Veja o [Guia de Customização da Interface do Usuário](Customization-User-Interface.md) para aprender como substituir componentes, personalizar e estender a interface do usuário.
### Copiar e Personalizar
Você pode executar o seguinte comando [ABP CLI](../../CLI.md) no diretório do projeto **Web** para copiar o código-fonte para a sua solução:
`abp add-module Volo.BasicTheme --with-source-code --add-to-solution-file`
----
Ou, você pode baixar o [código-fonte](https://github.com/abpframework/abp/tree/dev/modules/basic-theme/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic) do Tema Básico, copiar manualmente o conteúdo do projeto para a sua solução, reorganizar as dependências de pacote/módulo (veja a seção de Instalação acima para entender como ele foi instalado no projeto) e personalizar livremente o tema com base nos requisitos da sua aplicação.
## Veja também
* [Theming](Theming.md)

45
docs/pt-BR/UI/AspNetCore/Branding.md

@ -0,0 +1,45 @@
# ASP.NET Core MVC / Razor Pages: Branding
## IBrandingProvider
`IBrandingProvider` é uma interface simples que é usada para mostrar o nome e o logotipo da aplicação no layout.
A captura de tela abaixo mostra *MyProject* como o nome da aplicação:
![branding-nobrand](../../images/branding-nobrand.png)
Você pode implementar a interface `IBrandingProvider` ou herdar da classe `DefaultBrandingProvider` para definir o nome da aplicação:
````csharp
using Volo.Abp.Ui.Branding;
using Volo.Abp.DependencyInjection;
namespace MyProject.Web
{
[Dependency(ReplaceServices = true)]
public class MyProjectBrandingProvider : DefaultBrandingProvider
{
public override string AppName => "Book Store";
public override string LogoUrl => "/logo.png";
}
}
````
> Atualmente, definir o `AppName` só é aplicável ao [Tema Básico](../../Themes/Basic.md), não tem efeito nos outros [temas oficiais](../../Themes/Index.md).
O resultado será como mostrado abaixo:
![bookstore-added-logo](../../images/bookstore-added-logo.png)
`IBrandingProvider` possui as seguintes propriedades:
* `AppName`: O nome da aplicação.
* `LogoUrl`: Uma URL para mostrar o logotipo da aplicação.
* `LogoReverseUrl`: Uma URL para mostrar o logotipo da aplicação em um tema de cor reversa (escuro, por exemplo).
> **Dica**: `IBrandingProvider` é usado em cada atualização de página. Para uma aplicação multi-inquilino, você pode retornar um nome de aplicação específico do inquilino para personalizá-lo por inquilino.
## Sobrescrevendo a Área de Branding
Você pode consultar o [Guia de Customização de UI](Customization-User-Interface.md) para aprender como substituir a área de branding por um componente de visualização personalizado.

479
docs/pt-BR/UI/AspNetCore/Bundling-Minification.md

@ -0,0 +1,479 @@
# ASP.NET Core MVC Bundling & Minification
Existem várias maneiras de agrupar e minificar recursos do lado do cliente (arquivos JavaScript e CSS). As formas mais comuns são:
* Usando a extensão do Visual Studio [Bundler & Minifier](https://marketplace.visualstudio.com/items?itemName=MadsKristensen.BundlerMinifier) ou o [pacote NuGet](https://www.nuget.org/packages/BuildBundlerMinifier/).
* Usando os gerenciadores de tarefas [Gulp](https://gulpjs.com/)/[Grunt](https://gruntjs.com/) e seus plugins.
O ABP oferece uma maneira simples, dinâmica, poderosa, modular e integrada.
## Pacote Volo.Abp.AspNetCore.Mvc.UI.Bundling
> Este pacote já está instalado por padrão nos modelos de inicialização. Portanto, na maioria das vezes, você não precisa instalá-lo manualmente.
Se você não estiver usando um modelo de inicialização, pode usar o [ABP CLI](../../CLI.md) para instalá-lo em seu projeto. Execute o seguinte comando na pasta que contém o arquivo .csproj do seu projeto:
````
abp add-package Volo.Abp.AspNetCore.Mvc.UI.Bundling
````
> Se você ainda não o fez, primeiro precisa instalar o [ABP CLI](../../CLI.md). Para outras opções de instalação, consulte [a página de descrição do pacote](https://abp.io/package-detail/Volo.Abp.AspNetCore.Mvc.UI.Bundling).
## Tag Helpers de Agrupamento Razor
A maneira mais simples de criar um pacote é usar os tag helpers `abp-script-bundle` ou `abp-style-bundle`. Exemplo:
````html
<abp-style-bundle name="MyGlobalBundle">
<abp-style src="/libs/bootstrap/css/bootstrap.css" />
<abp-style src="/libs/font-awesome/css/font-awesome.css" />
<abp-style src="/libs/toastr/toastr.css" />
<abp-style src="/styles/my-global-style.css" />
</abp-style-bundle>
````
Este pacote define um pacote de estilo com um **nome único**: `MyGlobalBundle`. É muito fácil entender como usá-lo. Vamos ver como ele *funciona*:
* O ABP cria o pacote como **lazy** a partir dos arquivos fornecidos quando é **solicitado pela primeira vez**. Para as chamadas subsequentes, ele é retornado do **cache**. Isso significa que, se você adicionar condicionalmente os arquivos ao pacote, ele será executado apenas uma vez e quaisquer alterações na condição não afetarão o pacote para as próximas solicitações.
* O ABP adiciona os arquivos do pacote **individualmente** à página para o ambiente `development`. Ele agrupa e minifica automaticamente para outros ambientes (`staging`, `production`...). Consulte a seção *Modo de Agrupamento* para alterar esse comportamento.
* Os arquivos do pacote podem ser arquivos **físicos** ou [**virtuais/embutidos**](../../Virtual-File-System.md).
* O ABP adiciona automaticamente uma **string de consulta de versão** ao URL do arquivo do pacote para evitar que os navegadores armazenem em cache quando o pacote está sendo atualizado. (como ?_v=67872834243042 - gerado a partir da última data de alteração dos arquivos relacionados). A versão funciona mesmo se os arquivos do pacote forem adicionados individualmente à página (no ambiente de desenvolvimento).
### Importando os Tag Helpers de Agrupamento
> Isso já é importado por padrão nos modelos de inicialização. Portanto, na maioria das vezes, você não precisa adicioná-lo manualmente.
Para usar os tag helpers de pacote, você precisa adicioná-los ao seu arquivo `_ViewImports.cshtml` ou à sua página:
````
@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bundling
````
### Pacotes sem nome
O nome é **opcional** para os tag helpers de pacote razor. Se você não definir um nome, ele será **calculado** automaticamente com base nos nomes dos arquivos do pacote usados (eles são **concatenados** e **hashados**). Exemplo:
````html
<abp-style-bundle>
<abp-style src="/libs/bootstrap/css/bootstrap.css" />
<abp-style src="/libs/font-awesome/css/font-awesome.css" />
<abp-style src="/libs/toastr/toastr.css" />
@if (ViewBag.IncludeCustomStyles != false)
{
<abp-style src="/styles/my-global-style.css" />
}
</abp-style-bundle>
````
Isso pode criar **dois pacotes diferentes** (um inclui o `my-global-style.css` e o outro não).
Vantagens de pacotes **sem nome**:
* É possível **adicionar itens condicionalmente** ao pacote. Mas isso pode levar a várias variações do pacote com base nas condições.
Vantagens de pacotes **com nome**:
* Outros **módulos podem contribuir** para o pacote pelo nome (consulte as seções abaixo).
### Arquivo Único
Se você precisa apenas adicionar um único arquivo à página, pode usar a tag `abp-script` ou `abp-style` sem envolvê-la na tag `abp-script-bundle` ou `abp-style-bundle`. Exemplo:
````xml
<abp-script src="/scripts/my-script.js" />
````
O nome do pacote será *scripts.my-scripts* para o exemplo acima ("/" é substituído por "."). Todos os recursos de agrupamento funcionam como esperado para pacotes de arquivo único também.
## Opções de Agrupamento
Se você precisa usar o mesmo pacote em **múltiplas páginas** ou deseja usar alguns recursos mais **poderosos**, você pode configurar pacotes **por código** em sua classe de [módulo](../../Module-Development-Basics.md).
### Criando um Novo Pacote
Exemplo de uso:
````C#
[DependsOn(typeof(AbpAspNetCoreMvcUiBundlingModule))]
public class MyWebModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpBundlingOptions>(options =>
{
options
.ScriptBundles
.Add("MyGlobalBundle", bundle => {
bundle.AddFiles(
"/libs/jquery/jquery.js",
"/libs/bootstrap/js/bootstrap.js",
"/libs/toastr/toastr.min.js",
"/scripts/my-global-scripts.js"
);
});
});
}
}
````
> Você pode usar o mesmo nome (*MyGlobalBundle* aqui) para um pacote de script e estilo, pois eles são adicionados a coleções diferentes (`ScriptBundles` e `StyleBundles`).
Após definir um pacote desse tipo, ele pode ser incluído em uma página usando os mesmos tag helpers definidos acima. Exemplo:
````html
<abp-script-bundle name="MyGlobalBundle" />
````
Desta vez, nenhum arquivo é definido na definição do tag helper porque os arquivos do pacote são definidos pelo código.
### Configurando um Pacote Existente
O ABP também oferece suporte à [modularidade](../../Module-Development-Basics.md) para agrupamento. Um módulo pode modificar um pacote existente criado por um módulo dependente. Exemplo:
````C#
[DependsOn(typeof(MyWebModule))]
public class MyWebExtensionModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpBundlingOptions>(options =>
{
options
.ScriptBundles
.Configure("MyGlobalBundle", bundle => {
bundle.AddFiles(
"/scripts/my-extension-script.js"
);
});
});
}
}
````
Você também pode usar o método `ConfigureAll` para configurar todos os pacotes existentes:
````C#
[DependsOn(typeof(MyWebModule))]
public class MyWebExtensionModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpBundlingOptions>(options =>
{
options
.ScriptBundles
.ConfigureAll(bundle => {
bundle.AddFiles(
"/scripts/my-extension-script.js"
);
});
});
}
}
````
## Contribuidores de Pacotes
Adicionar arquivos a um pacote existente é útil. E se você precisar **substituir** um arquivo no pacote ou quiser adicionar arquivos **condicionalmente**? Definir um contribuidor de pacote fornece poder extra para esses casos.
Um exemplo de contribuidor de pacote que substitui o bootstrap.css por uma versão personalizada:
````C#
public class MyExtensionGlobalStyleContributor : BundleContributor
{
public override void ConfigureBundle(BundleConfigurationContext context)
{
context.Files.ReplaceOne(
"/libs/bootstrap/css/bootstrap.css",
"/styles/extensions/bootstrap-customized.css"
);
}
}
````
Em seguida, você pode usar esse contribuidor da seguinte maneira:
````C#
services.Configure<AbpBundlingOptions>(options =>
{
options
.ScriptBundles
.Configure("MyGlobalBundle", bundle => {
bundle.AddContributors(typeof(MyExtensionGlobalStyleContributor));
});
});
````
> Você também pode adicionar contribuidores ao criar um novo pacote.
Os contribuidores também podem ser usados nos tag helpers de pacote. Exemplo:
````xml
<abp-style-bundle>
<abp-style type="@typeof(BootstrapStyleContributor)" />
<abp-style src="/libs/font-awesome/css/font-awesome.css" />
<abp-style src="/libs/toastr/toastr.css" />
</abp-style-bundle>
````
As tags `abp-style` e `abp-script` podem receber atributos `type` (em vez de atributos `src`) como mostrado neste exemplo. Quando você adiciona um contribuidor de pacote, suas dependências também são adicionadas automaticamente ao pacote.
### Dependências de Contribuidores
Um contribuidor de pacote pode ter uma ou mais dependências de outros contribuidores.
Exemplo:
````C#
[DependsOn(typeof(MyDependedBundleContributor))] //Define a dependência
public class MyExtensionStyleBundleContributor : BundleContributor
{
//...
}
````
Quando um contribuidor de pacote é adicionado, suas dependências são adicionadas **automaticamente e recursivamente**. As dependências são adicionadas pela **ordem de dependência** evitando **duplicatas**. As duplicatas são evitadas mesmo que estejam em pacotes separados. O ABP organiza todos os pacotes em uma página e elimina duplicações.
Criar contribuidores e definir dependências é uma maneira de organizar a criação de pacotes em diferentes módulos.
### Extensões de Contribuidores
Em alguns cenários avançados, você pode querer fazer alguma configuração adicional sempre que um contribuidor de pacote for usado. As extensões de contribuidor funcionam perfeitamente quando o contribuidor estendido é usado.
O exemplo abaixo adiciona alguns estilos para a biblioteca prism.js:
````csharp
public class MyPrismjsStyleExtension : BundleContributor
{
public override void ConfigureBundle(BundleConfigurationContext context)
{
context.Files.AddIfNotContains("/libs/prismjs/plugins/toolbar/prism-toolbar.css");
}
}
````
Em seguida, você pode configurar `AbpBundleContributorOptions` para estender o `PrismjsStyleBundleContributor` existente.
````csharp
Configure<AbpBundleContributorOptions>(options =>
{
options
.Extensions<PrismjsStyleBundleContributor>()
.Add<MyPrismjsStyleExtension>();
});
````
Sempre que `PrismjsStyleBundleContributor` for adicionado a um pacote, `MyPrismjsStyleExtension` também será adicionado automaticamente.
### Acessando o IServiceProvider
Embora raramente seja necessário, `BundleConfigurationContext` possui uma propriedade `ServiceProvider` que permite resolver dependências de serviço dentro do método `ConfigureBundle`.
### Contribuidores de Pacotes Padrão
Adicionar um recurso específico do pacote NPM (arquivos js, css) a um pacote é bastante simples para esse pacote. Por exemplo, você sempre adiciona o arquivo `bootstrap.css` para o pacote NPM do bootstrap.
Existem contribuidores embutidos para todos os [pacotes NPM padrão](Client-Side-Package-Management.md). Por exemplo, se seu contribuidor depende do bootstrap, você pode apenas declará-lo, em vez de adicionar o bootstrap.css você mesmo.
````C#
[DependsOn(typeof(BootstrapStyleContributor))] //Define a dependência de estilo do bootstrap
public class MyExtensionStyleBundleContributor : BundleContributor
{
//...
}
````
Usando os contribuidores embutidos para pacotes padrão;
* Impede que você digite **os caminhos de recursos inválidos**.
* Impede a alteração do seu contribuidor se o **caminho do recurso mudar** (o contribuidor dependente lidará com isso).
* Impede que vários módulos adicionem **arquivos duplicados**.
* Gerencia **dependências recursivamente** (adiciona dependências de dependências, se necessário).
#### Pacote Volo.Abp.AspNetCore.Mvc.UI.Packages
> Este pacote já está instalado por padrão nos modelos de inicialização. Portanto, na maioria das vezes, você não precisa instalá-lo manualmente.
Se você não estiver usando um modelo de inicialização, pode usar o [ABP CLI](../../CLI.md) para instalá-lo em seu projeto. Execute o seguinte comando na pasta que contém o arquivo .csproj do seu projeto:
````
abp add-package Volo.Abp.AspNetCore.Mvc.UI.Packages
````
> Se você ainda não o fez, primeiro precisa instalar o [ABP CLI](../../CLI.md). Para outras opções de instalação, consulte [a página de descrição do pacote](https://abp.io/package-detail/Volo.Abp.AspNetCore.Mvc.UI.Packages).
### Herança de Pacotes
Em alguns casos específicos, pode ser necessário criar um **novo** pacote **herdado** de outro(s) pacote(s). Ao herdar de um pacote (recursivamente), todos os arquivos/contribuidores desse pacote são herdados. Em seguida, o pacote derivado pode adicionar ou modificar arquivos/contribuidores **sem modificar** o pacote original.
Exemplo:
````c#
services.Configure<AbpBundlingOptions>(options =>
{
options
.StyleBundles
.Add("MyTheme.MyGlobalBundle", bundle => {
bundle
.AddBaseBundles("MyGlobalBundle") //Pode adicionar vários
.AddFiles(
"/styles/mytheme-global-styles.css"
);
});
});
````
## Opções Adicionais
Esta seção mostra outras opções úteis para o sistema de agrupamento e minificação.
### Modo de Agrupamento
O ABP adiciona arquivos de pacote individualmente à página para o ambiente `development`. Ele agrupa e minifica automaticamente para outros ambientes (`staging`, `production`...). Na maioria das vezes, esse é o comportamento desejado. No entanto, você pode configurá-lo manualmente em alguns casos. Existem quatro modos;
* `Auto`: Determina automaticamente o modo com base no ambiente.
* `None`: Sem agrupamento ou minificação.
* `Bundle`: Agrupado, mas não minificado.
* `BundleAndMinify`: Agrupado e minificado.
Você pode configurar `AbpBundlingOptions` no `ConfigureServices` do seu [módulo](../../Module-Development-Basics.md).
**Exemplo:**
````csharp
Configure<AbpBundlingOptions>(options =>
{
options.Mode = BundlingMode.Bundle;
});
````
### Ignorar para Minificação
É possível ignorar um arquivo específico para a minificação.
**Exemplo:**
````csharp
Configure<AbpBundlingOptions>(options =>
{
options.MinificationIgnoredFiles.Add("/scripts/myscript.js");
});
````
O arquivo fornecido ainda é adicionado ao pacote, mas não é minificado neste caso.
### Carregar JavaScript e CSS de forma assíncrona
Você pode configurar `AbpBundlingOptions` para carregar todos ou um único arquivo js/css de forma assíncrona.
**Exemplo:**
````csharp
Configure<AbpBundlingOptions>(options =>
{
options.PreloadStyles.Add("/__bundles/Basic.Global");
options.DeferScriptsByDefault = true;
});
````
**HTML de saída:**
````html
<link rel="preload" href="/__bundles/Basic.Global.F4FA61F368098407A4C972D0A6914137.css?_v=637697363694828051" as="style" onload="this.rel='stylesheet'"/>
<script defer src="/libs/timeago/locales/jquery.timeago.en.js?_v=637674729040000000"></script>
````
### Suporte a Arquivos Externos/CDN
O sistema de agrupamento reconhece automaticamente os arquivos externos/CDN e os adiciona à página sem nenhuma alteração.
#### Usando Arquivos Externos/CDN em `AbpBundlingOptions`
````csharp
Configure<AbpBundlingOptions>(options =>
{
options.StyleBundles
.Add("MyStyleBundle", configuration =>
{
configuration
.AddFiles("/styles/my-style1.css")
.AddFiles("/styles/my-style2.css")
.AddFiles("https://cdn.abp.io/bootstrap.css")
.AddFiles("/styles/my-style3.css")
.AddFiles("/styles/my-style4.css");
});
options.ScriptBundles
.Add("MyScriptBundle", configuration =>
{
configuration
.AddFiles("/scripts/my-script1.js")
.AddFiles("/scripts/my-script2.js")
.AddFiles("https://cdn.abp.io/bootstrap.js")
.AddFiles("/scripts/my-script3.js")
.AddFiles("/scripts/my-script4.js");
});
});
````
**HTML de saída:**
````html
<link rel="stylesheet" href="/__bundles/MyStyleBundle.EA8C28419DCA43363E9670973D4C0D15.css?_v=638331889644609730" />
<link rel="stylesheet" href="https://cdn.abp.io/bootstrap.css" />
<link rel="stylesheet" href="/__bundles/MyStyleBundle.AC2E0AA6C461A0949A1295E9BDAC049C.css?_v=638331889644623860" />
<script src="/__bundles/MyScriptBundle.C993366DF8840E08228F3EE685CB08E8.js?_v=638331889644937120"></script>
<script src="https://cdn.abp.io/bootstrap.js"></script>
<script src="/__bundles/MyScriptBundle.2E8D0FDC6334D2A6B847393A801525B7.js?_v=638331889644943970"></script>
````
#### Usando Arquivos Externos/CDN em Tag Helpers.
````html
<abp-style-bundle name="MyStyleBundle">
<abp-style src="/styles/my-style1.css" />
<abp-style src="/styles/my-style2.css" />
<abp-style src="https://cdn.abp.io/bootstrap.css" />
<abp-style src="/styles/my-style3.css" />
<abp-style src="/styles/my-style4.css" />
</abp-style-bundle>
<abp-script-bundle name="MyScriptBundle">
<abp-script src="/scripts/my-script1.js" />
<abp-script src="/scripts/my-script2.js" />
<abp-script src="https://cdn.abp.io/bootstrap.js" />
<abp-script src="/scripts/my-script3.js" />
<abp-script src="/scripts/my-script4.js" />
</abp-script-bundle>
````
**HTML de saída:**
````html
<link rel="stylesheet" href="/__bundles/MyStyleBundle.C60C7B9C1F539659623BB6E7227A7C45.css?_v=638331889645002500" />
<link rel="stylesheet" href="https://cdn.abp.io/bootstrap.css" />
<link rel="stylesheet" href="/__bundles/MyStyleBundle.464328A06039091534650B0E049904C6.css?_v=638331889645012300" />
<script src="/__bundles/MyScriptBundle.55FDCBF2DCB9E0767AE6FA7487594106.js?_v=638331889645050410"></script>
<script src="https://cdn.abp.io/bootstrap.js"></script>
<script src="/__bundles/MyScriptBundle.191CB68AB4F41C8BF3A7AE422F19A3D2.js?_v=638331889645055490"></script>
````
## Temas
Os temas usam os contribuidores de pacotes padrão para adicionar recursos de biblioteca aos layouts de página. Os temas também podem definir alguns pacotes padrão/globais, para que qualquer módulo possa contribuir para esses pacotes padrão/globais. Consulte a documentação de [temas](Theming.md) para mais informações.
## Melhores Práticas e Sugestões
É sugerido definir vários pacotes para uma aplicação, cada um usado para diferentes propósitos.
* **Pacote global**: Pacotes de estilo/script globais são incluídos em todas as páginas da aplicação. Os temas já definem pacotes de estilo e script globais. Seu módulo pode contribuir para eles.
* **Pacotes de layout**: Este é um pacote específico para um layout individual. Contém apenas recursos compartilhados entre todas as páginas que usam o layout. Use os tag helpers de agrupamento para criar o pacote como uma boa prática.
* **Pacotes de módulo**: Para recursos compartilhados entre as páginas de um módulo individual.
* **Pacotes de página**: Pacotes específicos criados para cada página. Use os tag helpers de agrupamento para criar o pacote como uma melhor prática.
Estabeleça um equilíbrio entre desempenho, uso de largura de banda da rede e quantidade de pacotes.
## Veja também
* [Gerenciamento de Pacotes do Lado do Cliente](Client-Side-Package-Management.md)
* [Temas](Theming.md)

115
docs/pt-BR/UI/AspNetCore/Client-Side-Package-Management.md

@ -0,0 +1,115 @@
## Gerenciamento de Pacotes do Lado do Cliente no ASP.NET Core MVC
O framework ABP pode funcionar com qualquer tipo de sistema de gerenciamento de pacotes do lado do cliente. Você até pode decidir não usar nenhum sistema de gerenciamento de pacotes e gerenciar suas dependências manualmente.
No entanto, o framework ABP funciona melhor com o **NPM/Yarn**. Por padrão, os módulos integrados são configurados para funcionar com o NPM/Yarn.
Por fim, sugerimos o [**Yarn**](https://classic.yarnpkg.com/) em vez do NPM, pois ele é mais rápido, estável e também compatível com o NPM.
### Pacotes NPM do ABP
O ABP é uma plataforma modular. Todo desenvolvedor pode criar módulos e os módulos devem funcionar juntos em um estado **compatível** e **estável**.
Um desafio são as **versões dos pacotes NPM dependentes**. E se dois módulos diferentes usarem a mesma biblioteca JavaScript, mas em versões diferentes (e potencialmente incompatíveis)?
Para resolver o problema de versionamento, criamos um **conjunto padrão de pacotes** que dependem de algumas bibliotecas de terceiros comuns. Alguns exemplos de pacotes são [@abp/jquery](https://www.npmjs.com/package/@abp/jquery), [@abp/bootstrap](https://www.npmjs.com/package/@abp/bootstrap) e [@abp/font-awesome](https://www.npmjs.com/package/@abp/font-awesome). Você pode ver a **lista de pacotes** no [repositório do GitHub](https://github.com/volosoft/abp/tree/master/npm/packs).
A vantagem de um **pacote padrão** é:
* Ele depende de uma **versão padrão** de um pacote. Depender desse pacote é **seguro** porque todos os módulos dependem da mesma versão.
* Ele contém os mapeamentos para copiar os recursos da biblioteca (arquivos js, css, img...) da pasta `node_modules` para a pasta `wwwroot/libs`. Consulte a seção *Mapeando os Recursos da Biblioteca* para mais informações.
Depender de um pacote padrão é fácil. Basta adicioná-lo ao seu arquivo **package.json** como você normalmente faria. Exemplo:
```json
{
...
"dependencies": {
"@abp/bootstrap": "^1.0.0"
}
}
```
É sugerido depender de um pacote padrão em vez de depender diretamente de um pacote de terceiros.
#### Instalação do Pacote
Depois de depender de um pacote NPM, tudo o que você precisa fazer é executar o comando **yarn** no terminal para instalar todos os pacotes e suas dependências:
```bash
yarn
```
Alternativamente, você pode usar `npm install`, mas o [Yarn](https://classic.yarnpkg.com/) é sugerido como mencionado anteriormente.
#### Contribuição de Pacotes
Se você precisar de um pacote NPM de terceiros que não esteja no conjunto padrão de pacotes, você pode criar uma Pull Request no repositório do Github [repositório](https://github.com/volosoft/abp). Uma Pull Request que segue essas regras é aceita:
* O nome do pacote deve ser `@abp/nome-do-pacote` para um `nome-do-pacote` no NPM (exemplo: `@abp/bootstrap` para o pacote `bootstrap`).
* Deve ser a versão **mais recente estável** do pacote.
* Deve depender apenas de um pacote de terceiros. Pode depender de vários pacotes `@abp/*`.
* O pacote deve incluir um arquivo `abp.resourcemapping.js` formatado como definido na seção *Mapeando os Recursos da Biblioteca*. Este arquivo deve mapear apenas os recursos do pacote dependente.
* Você também precisa criar [contribuidor(es) de pacote](Bundling-Minification.md) para o pacote que você criou.
Veja os pacotes padrão atuais para exemplos.
### Mapeando os Recursos da Biblioteca
O uso de pacotes NPM e da ferramenta NPM/Yarn é o padrão de fato para bibliotecas do lado do cliente. A ferramenta NPM/Yarn cria uma pasta **node_modules** na pasta raiz do seu projeto da web.
O próximo desafio é copiar os recursos necessários (arquivos js, css, img...) da pasta `node_modules` para uma pasta dentro da pasta **wwwroot** para torná-los acessíveis aos clientes/navegadores.
O comando `abp install-libs` da CLI do ABP **copia os recursos** da pasta **node_modules** para a pasta **wwwroot/libs**. Cada **pacote padrão** (consulte a seção *@ABP NPM Packages*) define o mapeamento para seus próprios arquivos. Portanto, na maioria das vezes, você só precisa configurar as dependências.
Os modelos de inicialização já estão configurados para funcionar com tudo isso. Esta seção explicará as opções de configuração.
#### Arquivo de Definição de Mapeamento de Recursos
Um módulo deve definir um arquivo JavaScript chamado `abp.resourcemapping.js` formatado como no exemplo abaixo:
```json
module.exports = {
aliases: {
"@node_modules": "./node_modules",
"@libs": "./wwwroot/libs"
},
clean: [
"@libs",
"!@libs/**/foo.txt"
],
mappings: {
}
}
```
* A seção **aliases** define aliases padrão (placeholders) que podem ser usados nos caminhos de mapeamento. **@node_modules** e **@libs** são obrigatórios (pelos pacotes padrão), você pode definir seus próprios aliases para reduzir a duplicação.
* A seção **clean** é uma lista de pastas a serem limpas antes de copiar os arquivos. A correspondência de glob e a negação estão habilitadas, então você pode ajustar o que excluir e manter. O exemplo acima limpará tudo dentro de `./wwwroot/libs`, mas manterá quaisquer arquivos `foo.txt`.
* A seção **mappings** é uma lista de mapeamentos de arquivos/pastas a serem copiados. Este exemplo não copia nenhum recurso em si, mas depende de um pacote padrão.
Um exemplo de configuração de mapeamento é mostrado abaixo:
```json
mappings: {
"@node_modules/bootstrap/dist/css/bootstrap.css": "@libs/bootstrap/css/",
"@node_modules/bootstrap/dist/js/bootstrap.bundle.js": "@libs/bootstrap/js/",
"@node_modules/bootstrap-datepicker/dist/locales/*.*": "@libs/bootstrap-datepicker/locales/",
"@node_modules/bootstrap-v4-rtl/dist/**/*": "@libs/bootstrap-v4-rtl/dist/"
}
```
#### Comando install-libs
Depois de configurar corretamente o arquivo `abp.resourcemapping.js`, você pode executar o seguinte comando da CLI do ABP no terminal:
````bash
abp install-libs
````
Quando você executar este comando, todos os pacotes copiarão seus próprios recursos para a pasta `wwwroot/libs`. Executar `abp install-libs` é necessário apenas se você fizer uma alteração em suas dependências no arquivo **package.json**.
#### Veja também
* [Empacotamento e Minificação](Bundling-Minification.md)
* [Tematização](Theming.md)

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save