neozhu / CleanArchitectureWithBlazorServer

This is a repository for creating a Blazor Server dashboard application following the principles of Clean Architecture
https://architecture.blazorserver.com/
MIT License
763 stars 214 forks source link

[Feature/Issues]Empty Template #503

Closed bakes82 closed 7 months ago

bakes82 commented 1 year ago

I started ripping out some of the "example" stuff, so I can have a clean template to start from. Ideally Id think you would want this also, and then maintain another branch where you show the example, this way the base can easily maintained and then pull in the changes.

I also refactored, fixed naming/casing on some things. I also added some flags to enable hangfire, and was starting to do the auth. in the same way

Branch found here: https://github.com/bakes82/CleanArchitectureWithBlazorServer/tree/EmptyTemplate

Is multi tenancy a base feature or an example? I ripped out key values since it didnt implement multi tenant. Im almost to the point of ripping out multi tenant as it doesn't even seem the auth portion is using it, roles arent using it.

Current Google/MS auth is storing secrets etc in a js file that you can read publically. Also made no sense since the identity portion was basically configured. image

One of the service call implementations is marked as windows only? Why? Is there a windows only package, I didnt see anything that stood out in nuget?

To test auth: (I didnt try google) Add https://localhost:7256/signin-microsoft to the redirect url for the clientid/secret you have. (I havent implemented it creating a user or finalized the button styling on the login page since well multi tenancy isnt in yet)

Multi Tenancy Idea: (Note; the environment part could be more from me but I tend to have requirements to "test" something using another database for a tenant, so if in the tenant config we can setup multi DB connstrings and then swap them out) The login screen should also be updated to type in a tenant name/id (I wouldnt use auto filter since then someone can see every tenant name), when going to login page of a "tenant" the field is hidden, only appears on the "host"/root and is optional, as you still need a way to login to the host tenant.

public class TenantMiddleware
{
    private readonly RequestDelegate _next;
    private readonly IConfiguration _configuration;

    public TenantMiddleware(RequestDelegate next, IConfiguration configuration)
    {
        _next = next;
        _configuration = configuration;
    }

    public async Task InvokeAsync(HttpContext context, ITenantService tenantService)
    {
        string tenantIdentifier = null;
        string environment = "prod"; // Default environment

        // Extract tenant and environment method
        void ExtractTenantAndEnvironment(string input)
        {
            var parts = input.Split('-');
            tenantIdentifier = parts[0];
            if (parts.Length > 1)
            {
                environment = parts[1];
            }
        }

        // 1. Check for Subdomain:
        var baseDomain = _configuration["BaseDomain"];
        var host = context.Request.Host.Host;

        if (host.EndsWith(baseDomain))
        {
            var subdomainPart = host.Substring(0, host.Length - baseDomain.Length).TrimEnd('.');
            ExtractTenantAndEnvironment(subdomainPart);
        }

        // 2. Check for Header:
        if (string.IsNullOrEmpty(tenantIdentifier))
        {
            context.Request.Headers.TryGetValue("X-Tenant", out var tenantHeader);
            if (tenantHeader.Any())
            {
                ExtractTenantAndEnvironment(tenantHeader.FirstOrDefault());
            }
        }

        // 3. Check for Cookie:
        if (string.IsNullOrEmpty(tenantIdentifier))
        {
            context.Request.Cookies.TryGetValue("Tenant", out var tenantCookie);
            if (!string.IsNullOrEmpty(tenantCookie))
            {
                ExtractTenantAndEnvironment(tenantCookie);
            }
        }

        // 4. Check for URL string:
        if (string.IsNullOrEmpty(tenantIdentifier))
        {
            context.Request.Query.TryGetValue("tenant", out var tenantQuery);
            if (tenantQuery.Any())
            {
                ExtractTenantAndEnvironment(tenantQuery.FirstOrDefault());
            }
        }

        // If tenant is not identified, it'll be null. Proceed to check if tenant exists.
        var tenant = tenantService.GetTenantByIdentifier(tenantIdentifier);
        if (tenant != null)
        {
            context.Items["Tenant"] = tenant;
            context.Items["Environment"] = environment; // store the environment in the context
            await _next(context);
        }
        else
        {
            context.Response.StatusCode = 404; // Not Found
            await context.Response.WriteAsync("Tenant not found.");
            return;
        }
    }
}
Bram1903 commented 1 year ago

Having an empty template might indeed interest many people. I at least know many who would. We could have an clean template as main and besides that have en example branch which we can merge main into every time we improve the base. In that way the base keeps improving and we can freely add new work to an showcase project, which would show people what our base is capable of!

We should clear up some old branches anyway, but this is something @neozhu needs to look into, since I don't know what can't be removed.

neozhu commented 1 year ago

@bakes82,

Thank you for your helpful suggestions. I really appreciate your insights and expertise.

I'm particularly interested in your multi-tenancy implementation. I think it would be a great addition to the project, and I would love for you to contribute it.

Would you be willing to share your code as a pull request? I would be happy to merge it in.

Thanks again for your help!

Best,

neozhu commented 1 year ago

@bakes82 @Bram1903

I agree with your idea of creating multiple branches. It is a great way to keep the base clean and the example project up-to-date.

I'm not very familiar with git branching and merging, so I would be happy to have other developers who are more experienced with it join the project. We can work together to manage the branches and make sure that the project is well-maintained.

I really appreciate your contributions to the project. I know that your technical knowledge is far superior to mine.

Bram1903 commented 1 year ago

@bakes82 @Bram1903

I agree with your idea of creating multiple branches. It is a great way to keep the base clean and the example project up-to-date.

I'm not very familiar with git branching and merging, so I would be happy to have other developers who are more experienced with it join the project. We can work together to manage the branches and make sure that the project is well-maintained.

I really appreciate your contributions to the project. I know that your technical knowledge is far superior to mine.

Good morning,

Just a quick note: There's no need to worry about merging. What we're looking to do is pretty straightforward:

  1. Begin by creating a new branch from main.
  2. On this fresh branch, go ahead and remove any surplus showcase code.
  3. Now, change the name of the current branch to showcase. Simultaneously, rename the newly created stripped-down branch to main.
  4. Mark this refined main branch as the primary one.

By following this approach, anyone exploring our repository will immediately encounter a clean and ready-to-use template. Plus, we'll always have the Showcase branch on hand to illustrate the possibilities. This method significantly streamlines the process for others who want to base their projects on ours. It spares them the hassle of having to sift through unnecessary code, ultimately keeping their projects lean and efficient.

I understand that, even with my Collaborator permissions, I can't take care of setting or renaming default branches. However, these tasks are fairly simple and intuitive, so you shouldn't encounter any issues. In essence, we'll kick off the process by crafting the refined branch and removing any extraneous code. Once we're satisfied with this streamlined version, we can seamlessly rename the branches: making the clean variant the new main branch, while the current main becomes the showcase.

We need to always keep the showcase branch in sync with our cleaned-up variant branch. This means that any special settings or changes we make should be done in both branches. If we don't do this, our project could go in different directions, and that would make it hard to manage.

Kind regards,
Bram

Stonne commented 11 months ago

Hi Guys love the template... Empty template is great.. About multitenant have a look at finbuckle it is quite easy and works as a charm.... Have a nice day

neozhu commented 11 months ago

I'm interested in your implementation with finbuckle for multi-tenancy. Would you be willing to share your integration code or perhaps submit a PR? I'd be happy to consider merging this feature. Best regards.

Stonne commented 11 months ago

I had a look at it and the best way to start in my opinion is to have an empty repo without multitenancy to avoid mixing the two multitenant implementations. Maybe start with a 'howto implement finbuckle' guide ? Probably there will also be changes in the code generator extension. bakes82 is correct regarding the login screen for multitenant

neozhu commented 11 months ago

I looked into the documentation and issues regarding using Finbuckle.MultiTenant with Blazor server-side at (https://github.com/Finbuckle/Finbuckle.MultiTenant/issues/250). It seems there isn't a good solution yet, perhaps no one has tried it. I will give it a try to see

Stonne commented 11 months ago

Hi there,

I did it in a blazor wasm app…

But with the upcomming new Blazor in net 8.00 it might be better to wait and see then fort he implementation..

Best regards and keep up the good work…

Stonne

Van: neo.zhu @.> Verzonden: maandag 9 oktober 2023 12:18 Aan: neozhu/CleanArchitectureWithBlazorServer @.> CC: Gaston Holmgren @.>; Comment @.> Onderwerp: Re: [neozhu/CleanArchitectureWithBlazorServer] [Feature/Issues]Empty Template (Issue #503)

I looked into the documentation and issues regarding using Finbuckle.MultiTenant with Blazor server-side at (Finbuckle/Finbuckle.MultiTenant#250 https://github.com/Finbuckle/Finbuckle.MultiTenant/issues/250 ). It seems there isn't a good solution yet, perhaps no one has tried it. I will give it a try to see

— Reply to this email directly, view it on GitHub https://github.com/neozhu/CleanArchitectureWithBlazorServer/issues/503#issuecomment-1752733285 , or unsubscribe https://github.com/notifications/unsubscribe-auth/ABVNYOCLFXQCZDYQFNXHEPTX6PFL3AVCNFSM6AAAAAA4FEUIM6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTONJSG4ZTGMRYGU . You are receiving this because you commented.Message ID: @.***>

MatteoZampariniDev commented 10 months ago

I'm very interested in having an empty template but at the same time I think that there might be some problems in keeping the branches synched, I'll look for a solution when possible.

neozhu commented 10 months ago

Thank you for your input. I understand where you're coming from regarding the empty template. However, my perspective is that it's not necessary to have a blank template. I believe we should include some examples, like the Product and Customer objects, to help developer how this project was developed. As you may know, our project doesn't have comprehensive documentation. Thus, examining the code directly is the best way to understand its workings. Additionally, if someone doesn't want the Product and Customer components, they can easily delete them manually. It's quite straightforward.

MatteoZampariniDev commented 10 months ago

Thank you for your input. I understand where you're coming from regarding the empty template. However, my perspective is that it's not necessary to have a blank template. I believe we should include some examples, like the Product and Customer objects, to help developer how this project was developed. As you may know, our project doesn't have comprehensive documentation. Thus, examining the code directly is the best way to understand its workings. Additionally, if someone doesn't want the Product and Customer components, they can easily delete them manually. It's quite straightforward.

Yeah I didn't mean to replace the main branch with a blank template, just having both versions in order to jump start any new project easily without having to remove sample features every time for those who are already familiar with the architecture... I don't know if this is possible, if it is I wouldn't mind have that option too... otherwise it's not a big deal, anyone could create their own blank project by forking this one