Orchard multi tenancy without table/database proliferation - content-management-system

I'm looking at implemented a muli-tenant portal solution for my SaaS application using Orchard CMS. I'm pleased that it appears multi-tenancy is a first class feature, but it looks like in order to achieve it, I've got to either a) Create a set of tables for each tenant with a table prefix or b) Have separate databases for each tenant.
I'm trying to build a solution for 10,000+ customers, and so anything that requires me to make physical data schema changes per tenant won't scale. In our SaaS application, we use a tenantID column on all tables, plus the use of nHibernate filters and a heck of a lot of indexes to allow us to scale.
I'd like to do the same in Orchard. So instead of a table for each tenant, I'd like ONE set of tables with a tenantID, and then use filters in the data access layer (NHib) to always pull the right data.
Questions:
1) Is this possible?
2) Has anyone done this?
3) Any thoughts on the best way? I was going to modify the MultiTenancy/NHiberate module source directly.

It is possible, but quite hard to do.
It's also most likely not a scenario for Orchard multi-tenancy, but without any further details I cannot be sure.
This feature fits best in cases where you need to have a totally independent applications and (almost) nothing is supposed to be shared between them - like in shared hosting, for instance. The major drawback is the memory overhead, because each tenant has its own copy of the whole internal object infrastructure.
A much easier approach, instead of trying to put a square peg in a round hole tweaking multi-tenancy, would be to use single tenant and implement your desired multi-tenancy scheme in a separate module on your own, from scratch. You could eg. have a "Tenant" content type and build your module around it.

Related

MVC6 Identity3 - How to create common User Accounts for multiple WebApps

I'm new to MVC and currently working with MVC6 (EF7, Identity3, VS2015)...
I would like create two different/independent WebApps in one company domain (in different sub domains).
I would like use common/shared identity/login system for both Apps - in different words I would allow user to have one account across both Apps.
I do not have option for domain authentication (the company doesn't use the domain - I know it's weird), so I must? use Individual User Accounts...
What is the best way/practice to create and use common user account across multiple apps ?
In first place I thought about creating two different DBContext in both App: one for Identity (Users DB) and second for App-Related Db...
Such an approach would give me three different databases:
IdentityDb - common for both WebApps,
App1Db
App2Db
However I have doubts if it's good practice and the best way ?
Probably will be enough one DBContext with proper configuration, but I don't have idea where I should start.
I have read about SSO (Single Sign On) - but as far I understand it's about Authentication process, so it's little bit later - so I'm not sure about this direction.
Anyway can't find example how to create common user account/profile across multiple apps.
UPDATE:
My original question is probably too open... I would like ask not only 'what to do' but also 'how to do in MVC6'...
So my additional question is: how can I achieve this in MVC6? What I have to do? Perhaps some example?
If I decide for a separate User DB - then from the point of view of the application I will have two DB? What to do with this in code? Should I create two separate DBContexts - or just one?
Also I have read few opinion here on SO, that using only one DbContext is better and simpler option...
Anyway I have try yesterday works with 2x DBContext - everything works when I create new controller for IdentityDbContext, but I have error when trying create any controller for second DBContext (not associated with Identity)...
(I've put description of this error to new question: MVC6 Working with two DBContexts and error when create new controller)
Thanks in advance for any advice :)
The answer to your question if having three databases is the best way, is: It depends.
The answer to wether or not this is a good practice is irrelevant.
Let me elaborate.
The notion of every app having its dedicated database stems from old fashioned thinking. Big enterprise architectures are made up of all kinds of persistence storages, each chosen to do what it can do best. So it has nothing to do with good practices. You should store the data where it is suited best. Have a look at Domain Driven Design and Bounded Contexts in particular to get a better understanding of what I am talking about.
So the question if you need three databases, if in your particular situation this is the best option, then that is what you should do. To make this answer complete I' ll describe our situation. We have an old user database with users in it. We can't get rid of it untill all web apps have been phased out. To minimize the effect it has on our customers. So for our new web apps we only use this old database for the users and use azure storage for everything else we need to store. In other words, conceptually our situation is like what you describe. A seperate storage for the users that all other web apps use.
sounds like a good solution to the problem to you?
Update
As to MVC6, Identity Server 3 specific. ID server 3 has the ability to use custom User Service which allowes you to couple any user storage you want. Here are the details: https://identityserver.github.io/Documentation/docs/advanced/userService.html. This is exactly what we have done.
As for your other question; we will put the users in Azure Table Storage probably and retrieve it from there via IdentityServer4 when all old apps are gone. Right now there is nothing left in the legacy MySQL DB but users for us. But there are some old apps still using it, so...
Does this answer your questions?
In previous version of ASP.NET Identity (2) sharing identity cookie across subdomains was the sloution. I'm not sure about ver 3 but you can test it:
change Identity config in Configure method of Startup class:
services.AddIdentity<ApplicationUser, IdentityRole>(config =>
{
config.Cookies.ApplicationCookie.CookieDomain = ".domain.com";
})
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();

neo4j - graph database along with a relational database?

this is a question on best practice, i understand that there are a lot of different options for doing this, but i would like your opinions as to how you would approach solving this problem. Please take it as though performance is critical in this system, in other words scalable.
I have recently found the wonders of graph database, so i came up with a theoretical situation where a company wants to manage it's customers relationships, and in order to do so they are going to use neo4j which is great, and allows for really great management of the customers, different staff members and their relationships, which is all great, however the company now wants to create a web based interface which will need authentication, and anyone in the neo4j database should be able to login to the system in order to see how they are related to other people in the company's database, so each user must have a password/email/id associated with their name.
So my question is, in this case scenario, is it best to store the password_hash/password_salt/id/email in a mysql database and then based on the node look it up on the mysql database. Or is it better to store the password_hash/password_salt/id/email in the hash tables inside the nodes.
Also each store has 1000s of products, and they can be stored in the graph database or i can store the products in the mysql database and then look up the product there, and do the changes there, because the products are not related to each other, so no point in storing them in the graph database, so should they be not stored there to improve performance?
So my question boils down to this: is it best for large projects to use a graph database along with the more common rdms database such as mysql? if not, then what is the point at which you start to use these two database systems?
apologies in advance for my lack of knowledge regarding database terminology.
Graph DB is mainly used for maintaining relations. If app has a graph DB that does not mean that app needs to store everything in Graph DB.
Every node request on Graph is in memory and thus if you have unnecessary properties in your node it will be bloated and may make things slower and take more memory.I usually decide what needs to go in graph and what needs to go in DB by very simple rule.
High level property (that defines the relation and other important properties that defines the node) goes in graph whereas additional information goes in RDMS.
For example in FB may be FBID, Name goes in Graph as it defines the relationship of one node with another. But when user clicks on someones facebook ID, he/she gets to see other users DOB, Age , College .All these can go in RDBMS.
PS: RDMS has another advantage, it can be used for quick analytics. I know with graph also you can do that but i am not sure if its as scalable and easy as RDBMS.
Downside to this approach is : You need to maintain two DBS.
Unless you have a proven case for a two-DB solution, I'd say fewer moving parts would keep you more agile, more able to change things quickly. If later you find a use case that is difficult, then weigh up the cost/ benefit of introducing a second storage. A two-DB architecture is not unheard of, but comes with an overhead.
Specific to security, there is no reason why Neo4j or any other reasonable NOSQL solution couldn't do that: http://spring.neo4j.org/docs#tutorial_security
You should use both in case there is data where it does not make much sense to store it in a graph DB such as neo4j/orientDB (and some data would be better off in a graph DB as opposed to a relational DB). Forcing data on one platform may cause issues with performance/scalability down the line.

Creating an SaaS application that automates signup?

I'm looking for some guidance on my research to building an SaaS. This thread seems to be related, but I'm wondering if this software Rackspace has called rBuilder is what I would be looking for to automate the process of creating an instance of the software with a unique IP address and domain name.
Also, for an application similar to Shopify, does the application work like Facebook where it serves up different information based on the account, or is it better to have separate installs of the software like WordPress, but on a server that you maintain?
IMHO, there are various levels of Multi-tenancy [level1 through level4], among them, the purest form of multi-tenancy [Level4] is to have a single code base to cater to the needs of different customers [tenant's].
In this case, you will be required to maintain all of the configuration metadata within your code base to ensure that each tenant has the capability to customize the application the way they wanted to.
Having a single codebase is very clean, easier to maintain, easy to patch, easy to onboard new customers etc...
Hence, kindly note that you have to decide on the time and expense that you have budgeted for the application that you have planned to as the purest form of multi-tenancy does require some more additional thought process.
You can consult some articles like this and also google on the pros and con's of having the purest form of multi-tenancy vs on-premise model or virtualized model of multi-tenancy.
Also read more from here

Using the Entity Framework with multiple identical databases

I have a system where there are two identical databases. One is for back of house work where data is imported, edited generally worked on. Once the data in the first database is as required it is coped to the second database, which is used to drive a public facing (read only) site.
So once a month, or so I will need to push data from database to another. I'd like to drive all this with EF, is that reasonable, can EF do this kind of thing, or will I get stuck part way down the line?
It's probably doable, but frankly, EF (or any other ORM) is not really suited for this kind of task. If you do decide to implement your synchronization tool with EF, at least make sure to turn off change tracking.
I wouldn't dismiss Yuri's suggestion (simply using a scheduled backup/restore), if the databases are really identical. It's certainly the easiest to implement!
Another solution would be to use a database synchronization tool, like Sql Server Integration Services.

Using Postgresql as middle layer. Need opinion

I need some opinions.
I'm going to develop a POS and inventory software for a friend. This is a one man small scale project so I want to make the architecture as simple as possible.
I'm using Winform to develop the GUI (web interface doesn't make sense for POS software). For the database, I am using Postgresql.
The program will control access based on user roles, so either I have to develop a middle tier, using a web server, to control user access or I can just set user priveleges directly in Postgresql.
Developing a middle tier will be time consuming, and the maintenance will be more complex. So I prefer to set access control directly in the database.
Now it appears that using database to control user access is troublesome. I have to set priveleges for each role. Not to mention that for some tables, the priveleges are at column level. This makes reasoning about the security very hard.
So what I'm doing now is to set all the tables to be inaccessible except by superusers. The program will connect to the database using public role. Because the tables are inaccessible by public, I'm going to make publicly accessible stored functions with SECURITY DEFINER (with superuser role). The only way to access the tables is by using these functions.
I'll put the user roles and passwords in a table. Because the user table itself is inaccessible by non-superuser, I'll make a login function, let's call it fn_login(username, password). fn_login will return a session key if login is successful.
To call other functions, we need to supply session key for the user, e.g.: fn_purchase_list(session_key), fn_purchase_new(session_key, purchase_id, ...).
That way, I'm treating the stored functions as APIs. Adding new user will be easier as I only need to add new rows in the user table rather than adding new Postgresql roles. I won't need to set priveleges at column level. All controls will be done programmatically.
So what do you think? Is this approach feasible and scalable? Is there a better way to do it?
Thanks!
I believe there is a better way to do it. But since you haven't discussed what type of security you need, I cannot elaborate on specifics.
Since you are developing the application code in .NET, that code needs to be trusted (unlike a web application). Therefore, why don't you simply implement your roles and permissions in the application code, rather than the database?
My concern with your stated approach is the human overhead of stored procedures. Would much rather see you write the stated functions in C#, rather than in PostgreSQL. Then, standard version control and software development techniques could apply.
If you wait until somebody has at your database to check security, I think you'll be too late. That's a client/server mentality that went out at the end of the 90s. It's part of the reason why n-tier architectures came into vogue. Client/server can't scale horizontally as well as an n-tier solution.
I'd advise that you take better advantage of the middle tier. Security should be a cross-cutting concern that's further up the stack than your persistence layer.
If the MANAGEMENT of the database security is the issue, then you should add the task of automating that management. That means that you can store higher level data with the database tables, and then your application can convert that data in to the appropriate details and artifacts that the database requires.
It sounds like the database has the detail that you need, you just need to facilitate the management of that detail, and roll that in to your app.
My honest advice: Do not invent POS and inventory software. Take one of existing projects and make it better.