Skip to content

Commit

Permalink
feat: Add multi-tenancy to the template (#461)
Browse files Browse the repository at this point in the history
  • Loading branch information
ascott18 authored Sep 27, 2024
1 parent 63f8d86 commit 11a8dfa
Show file tree
Hide file tree
Showing 71 changed files with 3,107 additions and 920 deletions.
7 changes: 6 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,16 @@ jobs:
testCase:
# Nothing:
- ""
# Everything:
# Everything (except tenancy):
- "--Identity --MicrosoftAuth --GoogleAuth --UserPictures --AuditLogs --ExampleModel --DarkMode --TrackingBase --AppInsights --OpenAPI"
# Assorted partial variants:
- "--Identity --UserPictures --TrackingBase"
- "--Identity --MicrosoftAuth --AuditLogs"
# Tenancy variants:
- "--Identity --Tenancy --TenantCreateExternal --GoogleAuth"
- "--Identity --Tenancy --TenantCreateSelf --TenantMemberInvites --AuditLogs" # todo: add local accounts to this case when we add it
- "--Identity --Tenancy --TenantCreateAdmin --TenantMemberInvites --MicrosoftAuth" # todo: add local accounts to this case when we add it


defaults:
run:
Expand Down
6 changes: 4 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
# 5.0.2

- feat: better "not found" messages from data sources when the ID is null or empty string. (#447)
- feat: Make "not found" messages from data sources clearer when the ID is null or empty string. (#447)
- feat(template): Added multi-tenancy options to the template. (#441, #461)
- fix(template): adjust manual chunking configuration to avoid circular deps. (#455)
- fix(audit): key props now respect configured property exclusions
- fix(audit): key props now respect configured property exclusions.
- fix: c-admin-method now preserves newlines when displaying success messages.

# 5.0.1

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,12 @@
"
class="c-method--result-success"
>
<v-alert type="success" dense>{{
caller.message || "Success"
}}</v-alert>
<v-alert type="success" dense>
<span
class="text-pre-wrap"
v-text="caller.message || 'Success'"
></span>
</v-alert>
</span>

<div v-if="caller.result && methodMeta.return.type == 'file'">
Expand Down
8 changes: 5 additions & 3 deletions templates/Coalesce.Vue.Template/TestLocal.ps1
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
param (
[Parameter(Position=0)]
[Parameter(Position = 0)]
[string[]]$testCases
)

Expand All @@ -22,21 +22,23 @@ foreach ($testCase in $testCases) {
Write-Output "-------TEST CASE------"
if (-not $testCase) {
Write-Output "<no options enabled>"
} else {
}
else {
Write-Output $testCase
}
Write-Output "----------------------"
Write-Output ""

Remove-Item $dir/Test.Template.Instance/* -Recurse -Force -ErrorAction SilentlyContinue
Invoke-Expression "dotnet new coalescevue -o $dir/Test.Template.Instance $testcase"
Invoke-Expression "dotnet new coalescevue -o $dir/Test.Template.Instance --force $testcase"

Push-Location $dir/Test.Template.Instance/*.Web
try {
dotnet restore
dotnet coalesce
npm ci
npm run build
npm run lint:fix # ensure all lint issues are auto-fixable
dotnet build
}
finally {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,23 +41,23 @@
"datatype": "bool",
"displayName": "Sign-in with Microsoft",
"description": "Adds Microsoft as an external authentication and account provider for Identity.",
"$coalesceRequires": [ "and", "Identity" ],
"$coalesceRequires": ["and", "Identity"],
"$coalesceLink": "https://learn.microsoft.com/en-us/aspnet/core/security/authentication/social/microsoft-logins"
},
"GoogleAuth": {
"type": "parameter",
"datatype": "bool",
"displayName": "Sign-in with Google",
"description": "Adds Google as an external authentication and account provider for Identity.",
"$coalesceRequires": [ "and", "Identity" ],
"$coalesceRequires": ["and", "Identity"],
"$coalesceLink": "https://learn.microsoft.com/en-us/aspnet/core/security/authentication/social/google-logins"
},
"UserPictures": {
"type": "parameter",
"datatype": "bool",
"displayName": "User Profile Pictures",
"description": "Adds infrastructure for acquiring, saving, and displaying user profile pictures.",
"$coalesceRequires": [ "and", "Identity" ]
"$coalesceRequires": ["and", "Identity"]
},
"TrackingBase": {
"type": "parameter",
Expand Down Expand Up @@ -90,6 +90,45 @@
"displayName": "OpenAPI/Swagger",
"description": "Include configuration to expose an OpenAPI document and SwaggerUI using Swashbuckle."
},
"Tenancy": {
"type": "parameter",
"datatype": "bool",
"displayName": "Tenancy: Core",
"description": "Includes core infrastructure for supporting multiple tenants within one shared database, with shared user accounts.",
"$coalesceRequires": ["and", "Identity"]
},
"TenantCreateSelf": {
"type": "parameter",
"datatype": "bool",
"displayName": "Tenancy: Creation by Self-service",
"description": "Allows any signed in user to create additional tenants.",
"$coalesceRequires": ["and", "Tenancy"]
},
"TenantCreateAdmin": {
"type": "parameter",
"datatype": "bool",
"displayName": "Tenancy: Creation by Global Admin",
"description": "Allows global admins to create new tenants.",
"$coalesceRequires": ["and", "Tenancy"]
},
"TenantCreateExternal": {
"type": "parameter",
"datatype": "bool",
"displayName": "Tenancy: Creation/Membership by OIDC",
"description": "Automatically creates a new tenant for external organizations (Microsoft Entra, Google GSuite), and grants automatic tenant membership to other users within those organizations.",
"$coalesceRequires": [
"and",
"Tenancy",
["or", "MicrosoftAuth", "GoogleAuth"]
]
},
"TenantMemberInvites": {
"type": "parameter",
"datatype": "bool",
"displayName": "Tenancy: Membership by Invitation",
"description": "Allows administrators within a tenant to create invitation links to grant membership to their tenant.",
"$coalesceRequires": ["and", "Tenancy"]
},
"AppInsights": {
"type": "parameter",
"datatype": "bool",
Expand Down Expand Up @@ -131,11 +170,11 @@
{
"condition": "!Identity",
"exclude": [
"**/ProgramAuth.cs",
"**/AuthenticationConfiguration.cs",
"**/Forbidden.vue",
"**/UserAvatar.vue",
"**/SignIn.cshtml",
"**/SignIn.cshtml.cs",
"**/SignIn.*",
"**/SignOut.*",
"**/AppClaimTypes.cs",
"**/ClaimsPrincipalFactory.cs",
"**/Permission.cs",
Expand All @@ -144,6 +183,33 @@
"**/Role.cs"
]
},
{
"condition": "!MicrosoftAuth && !GoogleAuth",
"exclude": ["**/SignInService.cs"]
},
{
"condition": "!Tenancy",
"exclude": [
"**/Tenant.cs",
"**/DbContextFactoryExtensions.cs",
"**/TenantMembership.cs",
"**/ITenanted.cs",
"**/TenantedBase.cs",
"**/SelectTenant.*"
]
},
{
"condition": "!TenantCreateSelf",
"exclude": ["**/CreateTenant.*"]
},
{
"condition": "!(TenantMemberInvites || TenantCreateAdmin)",
"exclude": [
"**/Invitation.*",
"**/InvitationService.*",
"**/UserInvitation.*"
]
},
{
"condition": "!(UserPictures && Identity)",
"exclude": ["Coalesce.Starter.Vue.Data/Models/UserPhoto.cs"]
Expand All @@ -170,15 +236,19 @@
},
{
"condition": "!ExampleModel",
"exclude": ["**/WidgetEdit.vue", "**/WidgetEdit.spec.ts"]
"exclude": [
"**/WidgetEdit.vue",
"**/WidgetEdit.spec.ts",
"**/Widget.cs"
]
},
{
"condition": "!AzurePipelines",
"exclude": [ "**/azure-pipelines.yml" ]
"exclude": ["**/azure-pipelines.yml"]
},
{
"condition": "!GithubActions",
"exclude": [ "**/.github" ]
"exclude": ["**/.github"]
}
]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,24 @@ public SqliteDatabaseFixture()
using var db = new AppDbContextForSqlite(Options);

db.Database.EnsureCreated();
Seed();
Seed(db);
}

public void Seed()
public void Seed(AppDbContext db)
{
// Seed baseline test data, if desired.
var seeder = new DatabaseSeeder(db);
seeder.Seed();

#if Tenancy
if (!db.Tenants.Any())
{
var tenant = new Tenant { Name = "Test Tenant" };
db.Add(tenant);
db.SaveChanges();
db.TenantId = tenant.TenantId;
seeder.SeedNewTenant(tenant);
}
#endif
}

public void Dispose()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using IntelliTect.Coalesce;
using Coalesce.Starter.Vue.Data.Models;
using IntelliTect.Coalesce;
using IntelliTect.Coalesce.TypeDefinition;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;
Expand Down Expand Up @@ -82,6 +83,10 @@ private MockerScope BeginMockScope(bool standalone = false)
{
var mocker = new MockerScope(standalone ? null : this);
var db = new AppDbContextForSqlite(DbFixture.Options);
#if Tenancy
db.TenantId = db.Tenants.OrderBy(t => t.TenantId).First().TenantId;
#endif

mocker.Use(DbFixture.Options);
mocker.Use<AppDbContext>(db);

Expand Down
Loading

0 comments on commit 11a8dfa

Please sign in to comment.